diff --git a/Makefile.in b/Makefile.in index 2a87a8abdfc..94b9a08f862 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,7 +92,10 @@ include backend.RecursiveMakeBackend.pp default:: backend.RecursiveMakeBackend -install_manifests := bin idl include public private sdk +install_manifests := \ + $(addprefix dist/,bin idl include public private sdk) \ + _tests \ + $(NULL) install_manifest_depends = \ CLOBBER \ $(configure_dir)/configure \ @@ -110,7 +113,7 @@ endif endif .PHONY: install-manifests -install-manifests: $(addprefix install-dist-,$(install_manifests)) +install-manifests: $(addprefix install-,$(install_manifests)) # process_install_manifest needs to be invoked with --no-remove when building # js as standalone because automated builds are building nspr separately and @@ -121,15 +124,17 @@ ifdef JS_STANDALONE NO_REMOVE=1 endif -.PHONY: $(addprefix install-dist-,$(install_manifests)) -$(addprefix install-dist-,$(install_manifests)): install-dist-%: $(install_manifest_depends) +.PHONY: $(addprefix install-,$(install_manifests)) +$(addprefix install-,$(filter dist/%,$(install_manifests))): install-dist/%: $(install_manifest_depends) $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$*) -.PHONY: install-tests -install-manifests: install-tests -install-tests: $(install_manifest_depends) +install-_tests: $(install_manifest_depends) $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/tests) +# For compatibility +.PHONY: install-tests +install-tests: install-_tests + include $(topsrcdir)/build/moz-automation.mk # _tests should be purged during cleaning. However, we don't want it purged @@ -141,23 +146,25 @@ endif # Windows PGO builds don't perform a clean before the 2nd pass. So, we want # to preserve content for the 2nd pass on Windows. Everywhere else, we always # process the install manifests as part of export. +# For the binaries rule, not all the install manifests matter, so force only +# the interesting ones to be done. ifdef MOZ_PROFILE_USE ifndef NO_PROFILE_GUIDED_OPTIMIZE ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_) export:: install-manifests binaries:: - @$(MAKE) install-manifests NO_REMOVE=1 + @$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include endif endif else # !MOZ_PROFILE_USE (normal build) export:: install-manifests binaries:: - @$(MAKE) install-manifests NO_REMOVE=1 + @$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include endif # For historical reasons that are unknown, $(DIST)/sdk is always blown away # with no regard for PGO passes. This decision could probably be revisited. -export:: install-dist-sdk +export:: install-dist/sdk ifndef JS_STANDALONE ifdef ENABLE_TESTS diff --git a/accessible/base/SelectionManager.cpp b/accessible/base/SelectionManager.cpp index d846e356bc8..1469390b166 100644 --- a/accessible/base/SelectionManager.cpp +++ b/accessible/base/SelectionManager.cpp @@ -154,6 +154,12 @@ SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) return; Selection* selection = caretCntr->DOMSelection(); + + // XXX Sometimes we can't get a selection for caretCntr, in that case assume + // event->mSel is correct. + if (!selection) + selection = event->mSel; + mCaretOffset = caretCntr->DOMPointToOffset(selection->GetFocusNode(), selection->FocusOffset()); mAccWithCaret = caretCntr; @@ -179,8 +185,7 @@ SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument, logging::SelChange(aSelection, document, aReason); #endif - // Don't fire events until document is loaded. - if (document && document->IsContentLoaded()) { + if (document) { // Selection manager has longer lifetime than any document accessible, // so that we are guaranteed that the notification is processed before // the selection manager is destroyed. diff --git a/accessible/base/TreeWalker.cpp b/accessible/base/TreeWalker.cpp index 8e97e38c7a6..4ac1ee27b5f 100644 --- a/accessible/base/TreeWalker.cpp +++ b/accessible/base/TreeWalker.cpp @@ -12,36 +12,17 @@ #include "mozilla/dom/ChildIterator.h" #include "mozilla/dom/Element.h" +using namespace mozilla; using namespace mozilla::a11y; -//////////////////////////////////////////////////////////////////////////////// -// WalkState -//////////////////////////////////////////////////////////////////////////////// - -namespace mozilla { -namespace a11y { - -struct WalkState -{ - WalkState(nsIContent *aContent, uint32_t aFilter) : - content(aContent), prevState(nullptr), iter(aContent, aFilter) {} - - nsCOMPtr content; - WalkState *prevState; - dom::AllChildrenIterator iter; -}; - -} // namespace a11y -} // namespace mozilla - //////////////////////////////////////////////////////////////////////////////// // TreeWalker //////////////////////////////////////////////////////////////////////////////// TreeWalker:: TreeWalker(Accessible* aContext, nsIContent* aContent, uint32_t aFlags) : - mDoc(aContext->Document()), mContext(aContext), - mFlags(aFlags), mState(nullptr) + mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aContent), + mFlags(aFlags) { NS_ASSERTION(aContent, "No node for the accessible tree walker!"); @@ -50,17 +31,13 @@ TreeWalker:: mChildFilter |= nsIContent::eSkipPlaceholderContent; if (aContent) - mState = new WalkState(aContent, mChildFilter); + PushState(aContent); MOZ_COUNT_CTOR(TreeWalker); } TreeWalker::~TreeWalker() { - // Clear state stack from memory - while (mState) - PopState(); - MOZ_COUNT_DTOR(TreeWalker); } @@ -68,74 +45,66 @@ TreeWalker::~TreeWalker() // TreeWalker: private Accessible* -TreeWalker::NextChildInternal(bool aNoWalkUp) +TreeWalker::NextChild() { - if (!mState || !mState->content) + if (mStateStack.IsEmpty()) return nullptr; - while (nsIContent* childNode = mState->iter.GetNextChild()) { - bool isSubtreeHidden = false; - Accessible* accessible = mFlags & eWalkCache ? - mDoc->GetAccessible(childNode) : - GetAccService()->GetOrCreateAccessible(childNode, mContext, - &isSubtreeHidden); + dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1]; + while (top) { + while (nsIContent* childNode = top->GetNextChild()) { + bool isSubtreeHidden = false; + Accessible* accessible = mFlags & eWalkCache ? + mDoc->GetAccessible(childNode) : + GetAccService()->GetOrCreateAccessible(childNode, mContext, + &isSubtreeHidden); - if (accessible) - return accessible; - - // Walk down into subtree to find accessibles. - if (!isSubtreeHidden && childNode->IsElement()) { - PushState(childNode); - accessible = NextChildInternal(true); if (accessible) return accessible; + + // Walk down into subtree to find accessibles. + if (!isSubtreeHidden && childNode->IsElement()) + top = PushState(childNode); } + + top = PopState(); } - // No more children, get back to the parent. - nsIContent* anchorNode = mState->content; - PopState(); - if (aNoWalkUp) - return nullptr; - - if (mState) - return NextChildInternal(false); - // If we traversed the whole subtree of the anchor node. Move to next node // relative anchor node within the context subtree if possible. if (mFlags != eWalkContextTree) return nullptr; - while (anchorNode != mContext->GetNode()) { - nsINode* parentNode = anchorNode->GetFlattenedTreeParent(); + nsINode* contextNode = mContext->GetNode(); + while (mAnchorNode != contextNode) { + nsINode* parentNode = mAnchorNode->GetFlattenedTreeParent(); if (!parentNode || !parentNode->IsElement()) return nullptr; - PushState(parentNode->AsElement()); - while (nsIContent* childNode = mState->iter.GetNextChild()) { - if (childNode == anchorNode) - return NextChildInternal(false); + nsIContent* parent = parentNode->AsElement(); + top = mStateStack.AppendElement(dom::AllChildrenIterator(parent, + mChildFilter)); + while (nsIContent* childNode = top->GetNextChild()) { + if (childNode == mAnchorNode) { + mAnchorNode = parent; + return NextChild(); + } } - PopState(); - anchorNode = parentNode->AsElement(); + // XXX We really should never get here, it means we're trying to find an + // accessible for a dom node where iterating over its parent's children + // doesn't return it. However this sometimes happens when we're asked for + // the nearest accessible to place holder content which we ignore. + mAnchorNode = parent; } return nullptr; } -void +dom::AllChildrenIterator* TreeWalker::PopState() { - WalkState* prevToLastState = mState->prevState; - delete mState; - mState = prevToLastState; -} - -void -TreeWalker::PushState(nsIContent* aContent) -{ - WalkState* nextToLastState = new WalkState(aContent, mChildFilter); - nextToLastState->prevState = mState; - mState = nextToLastState; + size_t length = mStateStack.Length(); + mStateStack.RemoveElementAt(length - 1); + return mStateStack.IsEmpty() ? nullptr : &mStateStack[mStateStack.Length() - 1]; } diff --git a/accessible/base/TreeWalker.h b/accessible/base/TreeWalker.h index aa993b1679b..d34e5e9bb2e 100644 --- a/accessible/base/TreeWalker.h +++ b/accessible/base/TreeWalker.h @@ -8,6 +8,8 @@ #include "mozilla/Attributes.h" #include +#include "mozilla/dom/ChildIterator.h" +#include "nsCOMPtr.h" class nsIContent; @@ -17,8 +19,6 @@ namespace a11y { class Accessible; class DocAccessible; -struct WalkState; - /** * This class is used to walk the DOM tree to create accessible tree. */ @@ -50,43 +50,36 @@ public: * rejected during tree creation then the caller should be unbind it * from the document. */ - Accessible* NextChild() - { - return NextChildInternal(false); - } + Accessible* NextChild(); private: TreeWalker(); TreeWalker(const TreeWalker&); TreeWalker& operator =(const TreeWalker&); - /** - * Return the next child accessible. - * - * @param aNoWalkUp [in] specifies the walk direction, true means we - * shouldn't go up through the tree if we failed find - * accessible children. - */ - Accessible* NextChildInternal(bool aNoWalkUp); - /** * Create new state for the given node and push it on top of stack. * * @note State stack is used to navigate up/down the DOM subtree during * accessible children search. */ - void PushState(nsIContent* aNode); + dom::AllChildrenIterator* PushState(nsIContent* aContent) + { + return mStateStack.AppendElement(dom::AllChildrenIterator(aContent, + mChildFilter)); + } /** * Pop state from stack. */ - void PopState(); + dom::AllChildrenIterator* PopState(); DocAccessible* mDoc; Accessible* mContext; + nsIContent* mAnchorNode; + nsAutoTArray mStateStack; int32_t mChildFilter; uint32_t mFlags; - WalkState* mState; }; } // namespace a11y diff --git a/accessible/jsat/OutputGenerator.jsm b/accessible/jsat/OutputGenerator.jsm index bc0db475c78..7f9689f872a 100644 --- a/accessible/jsat/OutputGenerator.jsm +++ b/accessible/jsat/OutputGenerator.jsm @@ -596,6 +596,10 @@ this.UtteranceGenerator = { // jshint ignore:line aOutput.push({string: 'stateUnavailable'}); } + if (aState.contains(States.READONLY)) { + aOutput.push({string: 'stateReadonly'}); + } + // Don't utter this in Jelly Bean, we let TalkBack do it for us there. // This is because we expose the checked information on the node itself. // XXX: this means the checked state is always appended to the end, diff --git a/accessible/tests/mochitest/events.js b/accessible/tests/mochitest/events.js index 7782ceffb30..06935d48a4d 100644 --- a/accessible/tests/mochitest/events.js +++ b/accessible/tests/mochitest/events.js @@ -1743,10 +1743,11 @@ function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted, aFromUse /** * Caret move events checker. */ -function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg) +function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg, + aIsAsync) { this.__proto__ = new invokerChecker(EVENT_TEXT_CARET_MOVED, - aTargetOrFunc, aTargetFuncArg); + aTargetOrFunc, aTargetFuncArg, aIsAsync); this.check = function caretMoveChecker_check(aEvent) { @@ -1756,6 +1757,12 @@ function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg) } } +function asyncCaretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg) +{ + this.__proto__ = new caretMoveChecker(aCaretOffset, aTargetOrFunc, + aTargetFuncArg, true); +} + /** * Text selection change checker. */ diff --git a/accessible/tests/mochitest/events/a11y.ini b/accessible/tests/mochitest/events/a11y.ini index 50dd2e8060d..6b549c854ab 100644 --- a/accessible/tests/mochitest/events/a11y.ini +++ b/accessible/tests/mochitest/events/a11y.ini @@ -46,6 +46,7 @@ skip-if = os == 'win' || os == 'linux' [test_namechange.xul] [test_namechange.html] [test_scroll.xul] +[test_scroll_caret.xul] [test_selection.html] skip-if = buildapp == 'mulet' [test_selection.xul] diff --git a/accessible/tests/mochitest/events/scroll.html b/accessible/tests/mochitest/events/scroll.html index df71fd45946..562e0a38259 100644 --- a/accessible/tests/mochitest/events/scroll.html +++ b/accessible/tests/mochitest/events/scroll.html @@ -119,5 +119,63 @@ text text text text text text text text text text text text text text
text text text text text text text text text text text text text text

+ +

heading 1

+

+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+ text text text text text text text text text text text text text text
+

diff --git a/accessible/tests/mochitest/events/test_scroll_caret.xul b/accessible/tests/mochitest/events/test_scroll_caret.xul new file mode 100644 index 00000000000..57e27747f13 --- /dev/null +++ b/accessible/tests/mochitest/events/test_scroll_caret.xul @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + Mozilla Bug 1056459 + + +

+ +
+      
+ + + +
+
diff --git a/accessible/tests/mochitest/jsat/test_output.html b/accessible/tests/mochitest/jsat/test_output.html index 01b4e2ebef4..8a19d394277 100644 --- a/accessible/tests/mochitest/jsat/test_output.html +++ b/accessible/tests/mochitest/jsat/test_output.html @@ -232,6 +232,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 {"string": "entry"}]], expectedBraille: [[{"string": "entryAbbr"}, "I am required"], ["I am required", {"string": "entryAbbr"}]] + }, { + // test unavailable state utterance on inputs + accOrElmOrID: "readonlyInput", + expectedUtterance: [[{"string": "stateReadonly"}, {"string": "entry"}, + "No edits"], ["No edits", {"string": "stateReadonly"}, + {"string": "entry"}]], + expectedBraille: [[{"string": "entryAbbr"}, "No edits"], + ["No edits", {"string": "entryAbbr"}]] + }, { + // test unavailable state utterance on textareas + accOrElmOrID: "readonlyTextarea", + expectedUtterance: [[{"string": "stateReadonly"}, {"string": "textarea"}, + "No editing"], ["No editing", {"string": "stateReadonly"}, + {"string": "textarea"}]], + expectedBraille: [[{"string": "textareaAbbr"}, "No editing"], + ["No editing", {"string": "textareaAbbr"}]] }, { // test has popup state utterance accOrElmOrID: "hasPopupButton", @@ -486,6 +502,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 + +
Account diff --git a/accessible/tests/mochitest/text/test_words.html b/accessible/tests/mochitest/text/test_words.html index f282a062fee..dff90bfeab8 100644 --- a/accessible/tests/mochitest/text/test_words.html +++ b/accessible/tests/mochitest/text/test_words.html @@ -92,6 +92,8 @@ testWordAt("div17", 3, "you", kOk); testWordAt("div17", 4, "here", kTodo); + testWords("input_1", ["foo", "bar"]); + SimpleTest.finish(); } @@ -125,5 +127,7 @@
3+4*5=23
Hello. Friend, are you here?!
+ + diff --git a/addon-sdk/source/lib/sdk/system/child_process/subprocess.js b/addon-sdk/source/lib/sdk/system/child_process/subprocess.js index c445b6dda35..493583e6581 100644 --- a/addon-sdk/source/lib/sdk/system/child_process/subprocess.js +++ b/addon-sdk/source/lib/sdk/system/child_process/subprocess.js @@ -193,9 +193,9 @@ const LRESULT = ctypes.size_t; const ULONG_PTR = ctypes.uintptr_t; const PVOID = ctypes.voidptr_t; const LPVOID = PVOID; -const LPCTSTR = ctypes.jschar.ptr; -const LPCWSTR = ctypes.jschar.ptr; -const LPTSTR = ctypes.jschar.ptr; +const LPCTSTR = ctypes.char16_t.ptr; +const LPCWSTR = ctypes.char16_t.ptr; +const LPTSTR = ctypes.char16_t.ptr; const LPSTR = ctypes.char.ptr; const LPCSTR = ctypes.char.ptr; const LPBYTE = ctypes.char.ptr; @@ -707,8 +707,8 @@ function subprocess_win32(options) { if(environment.length) { //An environment block consists of //a null-terminated block of null-terminated strings. - //Using CREATE_UNICODE_ENVIRONMENT so needs to be jschar - environment = ctypes.jschar.array()(environment.join('\0') + '\0'); + //Using CREATE_UNICODE_ENVIRONMENT so needs to be char16_t + environment = ctypes.char16_t.array()(environment.join('\0') + '\0'); } else { environment = null; } diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index d002a1c69fb..f33f0c648d4 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -971,17 +971,17 @@ pref("apz.x_stationary_size_multiplier", "1.5"); pref("apz.y_stationary_size_multiplier", "1.8"); pref("apz.enlarge_displayport_when_clipped", true); // Use "sticky" axis locking -pref("apz.axis_lock_mode", 2); +pref("apz.axis_lock.mode", 2); pref("apz.subframe.enabled", true); // Overscroll-related settings pref("apz.overscroll.enabled", true); -pref("apz.overscroll.fling_friction", "0.02"); +pref("apz.overscroll.fling_friction", "0.05"); pref("apz.overscroll.fling_stopped_threshold", "0.4"); pref("apz.overscroll.stretch_factor", "0.5"); -pref("apz.overscroll.snap_back.spring_stiffness", "0.6"); +pref("apz.overscroll.snap_back.spring_stiffness", "0.05"); pref("apz.overscroll.snap_back.spring_friction", "0.1"); -pref("apz.overscroll.snap_back.mass", "1200"); +pref("apz.overscroll.snap_back.mass", "100"); // This preference allows FirefoxOS apps (and content, I think) to force // the use of software (instead of hardware accelerated) 2D canvases by @@ -1003,8 +1003,8 @@ pref("dom.wakelock.enabled", true); // Enable touch caret by default pref("touchcaret.enabled", true); -// Disable selection caret by default -pref("selectioncaret.enabled", false); +// Enable selection caret by default +pref("selectioncaret.enabled", true); // Enable sync and mozId with Firefox Accounts. pref("services.sync.fxaccounts.enabled", true); diff --git a/b2g/app/nsBrowserApp.cpp b/b2g/app/nsBrowserApp.cpp index 57a533ba103..69036a070ae 100644 --- a/b2g/app/nsBrowserApp.cpp +++ b/b2g/app/nsBrowserApp.cpp @@ -283,15 +283,17 @@ int main(int argc, _CONST char* argv[]) */ _argv = new char *[argc + 1]; for (int i = 0; i < argc; i++) { - _argv[i] = strdup(argv[i]); + size_t len = strlen(argv[i]) + 1; + _argv[i] = new char[len]; MOZ_ASSERT(_argv[i] != nullptr); + memcpy(_argv[i], argv[i], len); } _argv[argc] = nullptr; result = do_main(argc, _argv); for (int i = 0; i < argc; i++) { - free(_argv[i]); + delete[] _argv[i]; } delete[] _argv; } diff --git a/b2g/components/SystemAppProxy.jsm b/b2g/components/SystemAppProxy.jsm index 54bdb2b6991..fc44c7b1521 100644 --- a/b2g/components/SystemAppProxy.jsm +++ b/b2g/components/SystemAppProxy.jsm @@ -110,10 +110,10 @@ let SystemAppProxy = { if (content) { content.removeEventListener.apply(content, arguments); } else { - let idx = this._pendingListeners.indexOf(listener); - if (idx != -1) { - this._pendingListeners.splice(idx, 1); - } + this._pendingListeners = this._pendingListeners.filter( + args => { + return args[0] != name || args[1] != listener; + }); } }, diff --git a/b2g/components/test/mochitest/systemapp_helper.js b/b2g/components/test/mochitest/systemapp_helper.js index dfffcd3969e..80e30b0096d 100644 --- a/b2g/components/test/mochitest/systemapp_helper.js +++ b/b2g/components/test/mochitest/systemapp_helper.js @@ -94,7 +94,7 @@ let steps = [ // Ensure that listener being registered before the system app is ready // are correctly removed from the pending list function removedListener() { - assert(false, "Listener isn't correctly removed from the pending list"); + assert.ok(false, "Listener isn't correctly removed from the pending list"); } SystemAppProxy.addEventListener("mozChromeEvent", removedListener); SystemAppProxy.removeEventListener("mozChromeEvent", removedListener); diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 0459d237766..889e33ce938 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -120,14 +120,14 @@ - + - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 024cc6acdd9..3045b6f9624 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 85c7bf517d7..24043ad9964 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -130,6 +130,7 @@ + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 4819625f781..1cdc7c51b86 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 024cc6acdd9..3045b6f9624 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,13 +19,13 @@ - + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 2af82d93711..92bc54a8e40 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + @@ -23,7 +23,7 @@ - + @@ -132,7 +132,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 401325af0b6..1e1096a4179 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,10 +17,10 @@ - + - + @@ -122,7 +122,7 @@ - + diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d7e366e234b..cca134c91b9 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "c24176cfc9d128e5673782e05532f09ff94d09c5", + "revision": "d43b2e2dba496f624d62c1b72a22dc5e34953fbd", "repo_path": "/integration/gaia-central" } diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 2f99b159cc7..46efccca07e 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index bb4a0621727..2ceb321aa57 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 68e43094fd0..777547ad810 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,10 +17,10 @@ - + - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 664fd181a86..898a891345c 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,12 +17,12 @@ - + - + diff --git a/b2g/dev/app/moz.build b/b2g/dev/app/moz.build index bdb19346930..6fbe8159b2d 100644 --- a/b2g/dev/app/moz.build +++ b/b2g/dev/app/moz.build @@ -1,6 +1,3 @@ # 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/. - -DIST_SUBDIR = 'browser' -export('DIST_SUBDIR') diff --git a/browser/app/moz.build b/browser/app/moz.build index 3d22eab10b0..f6570585f06 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -72,3 +72,6 @@ if CONFIG['MOZ_LINKER']: if CONFIG['HAVE_CLOCK_MONOTONIC']: OS_LIBS += CONFIG['REALTIME_LIBS'] + +if CONFIG['MOZ_OPTIMIZE']: + DEFINES['MOZ_OPTIMIZE'] = True diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 9311f93041a..685631d90c7 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1131,13 +1131,6 @@ pref("browser.zoom.updateBackgroundTabs", true); // The breakpad report server to link to in about:crashes pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/"); -#ifndef RELEASE_BUILD -// Override submission of plugin hang reports to a different processing server -// for the smaller-volume nightly/aurora populations. -pref("toolkit.crashreporter.pluginHangSubmitURL", - "https://hang-reports.mozilla.org/submit"); -#endif - // URL for "Learn More" for Crash Reporter pref("toolkit.crashreporter.infoURL", "https://www.mozilla.org/legal/privacy/firefox.html#crash-reporter"); @@ -1184,6 +1177,25 @@ pref("browser.tabs.remote", false); #endif pref("browser.tabs.remote.autostart", false); +#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_WIN) +// This controls whether the content process on Windows is sandboxed. +// You also need to be using remote tabs, see above. +// on = full sandbox enabled +// warn = warn only sandbox enabled +// anything else = sandbox disabled +// This will probably require a restart. +pref("browser.tabs.remote.sandbox", "off"); + +// This is essentially the same logic that decides whether nsStackWalk.cpp gets +// built, which we use for the stack trace. See xpcom/base/moz.build +#if !defined(MOZ_OPTIMIZE) || defined(MOZ_PROFILING) || defined(DEBUG) +// This controls the depth of stack trace that is logged when the warn only +// sandbox reports that a resource access request has been blocked. +// This does not require a restart to take effect. +pref("browser.tabs.remote.sandbox.warnOnlyStackTraceDepth", 0); +#endif +#endif + // This pref governs whether we attempt to work around problems caused by // plugins using OS calls to manipulate the cursor while running out-of- // process. These workarounds all involve intercepting (hooking) certain @@ -1267,6 +1279,7 @@ pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true); pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true); pref("services.sync.prefs.sync.privacy.donottrackheader.value", true); pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true); +pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true); pref("services.sync.prefs.sync.security.OCSP.enabled", true); pref("services.sync.prefs.sync.security.OCSP.require", true); pref("services.sync.prefs.sync.security.default_personal_cert", true); diff --git a/browser/base/content/aboutneterror/netError.xhtml b/browser/base/content/aboutNetError.xhtml similarity index 99% rename from browser/base/content/aboutneterror/netError.xhtml rename to browser/base/content/aboutNetError.xhtml index e1f173f6d61..f7326af1775 100644 --- a/browser/base/content/aboutneterror/netError.xhtml +++ b/browser/base/content/aboutNetError.xhtml @@ -20,7 +20,6 @@ &loadError.label; - diff --git a/browser/base/content/aboutneterror/netError.css b/browser/base/content/aboutneterror/netError.css deleted file mode 100644 index 14b206b9954..00000000000 --- a/browser/base/content/aboutneterror/netError.css +++ /dev/null @@ -1,69 +0,0 @@ -/* 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/. */ - -@import url("chrome://global/skin/in-content/common.css"); - -body { - display: flex; - box-sizing: padding-box; - min-height: 100vh; - padding: 0 48px; - align-items: center; - justify-content: center; -} - -ul, ol { - margin: 0; - padding: 0; - -moz-margin-start: 1em; -} - -ul > li, ol > li { - margin-bottom: .5em; -} - -ul { - list-style: disc; -} - -#errorPageContainer { - min-width: 320px; - max-width: 512px; -} - -#errorTitleText { - background: url("info.svg") left 0 no-repeat; - background-size: 1.2em; - -moz-margin-start: -2em; - -moz-padding-start: 2em; -} - -#errorTitleText:-moz-dir(rtl) { - background-position: right 0; -} - -#errorTryAgain { - margin-top: 1.2em; - min-width: 150px -} - -#errorContainer { - display: none; -} - -@media (max-width: 675px) { - #errorTitleText { - padding-top: 0; - background-image: none; - -moz-padding-start: 0; - -moz-margin-start: 0; - } -} - -/* Pressing the retry button will cause the cursor to flicker from a pointer to - * not-allowed. Override the disabled cursor behaviour since we will never show - * the button disabled as the initial state. */ -button:disabled { - cursor: pointer; -} diff --git a/browser/base/content/browser-addons.js b/browser/base/content/browser-addons.js index 5698340514f..542f62f7ff1 100644 --- a/browser/base/content/browser-addons.js +++ b/browser/base/content/browser-addons.js @@ -44,8 +44,11 @@ const gXPInstallObserver = { } catch (e) { browser = winOrBrowser; } - if (!browser) + // Note that the above try/catch will pass through dead object proxies and + // other degenerate objects. Make sure the browser is bonafide. + if (!browser || gBrowser.browsers.indexOf(browser) == -1) return; + const anchorID = "addons-notification-icon"; var messageString, action; var brandShortName = brandBundle.getString("brandShortName"); @@ -80,8 +83,16 @@ const gXPInstallObserver = { action, null, options); break; case "addon-install-blocked": + let originatingHost; + try { + originatingHost = installInfo.originatingURI.host; + } catch (ex) { + // Need to deal with missing originatingURI and with about:/data: URIs more gracefully, + // see bug 1063418 - but for now, bail: + return; + } messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning", - [brandShortName, installInfo.originatingURI.host]); + [brandShortName, originatingHost]); let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI"); action = { diff --git a/browser/base/content/browser-places.js b/browser/base/content/browser-places.js index 3907daed592..f92e2639b43 100644 --- a/browser/base/content/browser-places.js +++ b/browser/base/content/browser-places.js @@ -504,12 +504,21 @@ function HistoryMenu(aPopupShowingEvent) { } HistoryMenu.prototype = { + _getClosedTabCount() { + // SessionStore doesn't track the hidden window, so just return zero then. + if (window == Services.appShell.hiddenDOMWindow) { + return 0; + } + + return SessionStore.getClosedTabCount(window); + }, + toggleRecentlyClosedTabs: function HM_toggleRecentlyClosedTabs() { // enable/disable the Recently Closed Tabs sub menu var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0]; // no restorable tabs, so disable menu - if (SessionStore.getClosedTabCount(window) == 0) + if (this._getClosedTabCount() == 0) undoMenu.setAttribute("disabled", true); else undoMenu.removeAttribute("disabled"); @@ -527,7 +536,7 @@ HistoryMenu.prototype = { undoPopup.removeChild(undoPopup.firstChild); // no restorable tabs, so make sure menu is disabled, and return - if (SessionStore.getClosedTabCount(window) == 0) { + if (this._getClosedTabCount() == 0) { undoMenu.setAttribute("disabled", true); return; } diff --git a/browser/base/content/browser-thumbnails.js b/browser/base/content/browser-thumbnails.js index bb2d2bce328..454a5022248 100644 --- a/browser/base/content/browser-thumbnails.js +++ b/browser/base/content/browser-thumbnails.js @@ -125,6 +125,10 @@ let gBrowserThumbnails = { // FIXME: This should be part of the PageThumbs API. (bug 1062414) _shouldCapture: function Thumbnails_shouldCapture(aBrowser) { + // Don't try to capture in e10s yet (because of bug 698371) + if (gMultiProcessBrowser) + return false; + // Capture only if it's the currently selected tab. if (aBrowser != gBrowser.selectedBrowser) return false; diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index d07579831e0..ff97b34b4dc 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -2336,6 +2336,9 @@ let BrowserOnClick = { let originalTarget = event.originalTarget; let ownerDoc = originalTarget.ownerDocument; + if (!ownerDoc) { + return; + } if (gMultiProcessBrowser && ownerDoc.documentURI.toLowerCase() == "about:newtab") { diff --git a/browser/base/content/content.js b/browser/base/content/content.js index 750ea6bc9dc..7550f13eb74 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -370,6 +370,9 @@ let ClickEventHandler = { let originalTarget = event.originalTarget; let ownerDoc = originalTarget.ownerDocument; + if (!ownerDoc) { + return; + } // Handle click events from about pages if (ownerDoc.documentURI.startsWith("about:certerror")) { diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js index b3dd06ede93..47528de5720 100644 --- a/browser/base/content/sanitize.js +++ b/browser/base/content/sanitize.js @@ -390,6 +390,11 @@ Sanitizer.prototype = { for each (var host in hosts) { pwmgr.setLoginSavingEnabled(host, true); } + + // Clear site security settings + var sss = Cc["@mozilla.org/ssservice;1"] + .getService(Ci.nsISiteSecurityService); + sss.clearAll(); }, get canClear() diff --git a/browser/base/content/sync/aboutSyncTabs.js b/browser/base/content/sync/aboutSyncTabs.js index 50073dfeb00..27af4448645 100644 --- a/browser/base/content/sync/aboutSyncTabs.js +++ b/browser/base/content/sync/aboutSyncTabs.js @@ -4,10 +4,22 @@ const Cu = Components.utils; +Cu.import("resource://services-common/utils.js"); Cu.import("resource://services-sync/main.js"); Cu.import("resource:///modules/PlacesUIUtils.jsm"); Cu.import("resource://gre/modules/PlacesUtils.jsm", this); Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); + +#ifdef MOZ_SERVICES_CLOUDSYNC +XPCOMUtils.defineLazyModuleGetter(this, "CloudSync", + "resource://gre/modules/CloudSync.jsm"); +#else +let CloudSync = null; +#endif let RemoteTabViewer = { _tabsList: null, @@ -16,6 +28,8 @@ let RemoteTabViewer = { Services.obs.addObserver(this, "weave:service:login:finish", false); Services.obs.addObserver(this, "weave:engine:sync:finish", false); + Services.obs.addObserver(this, "cloudsync:tabs:update", false); + this._tabsList = document.getElementById("tabsList"); this.buildList(true); @@ -24,63 +38,62 @@ let RemoteTabViewer = { uninit: function () { Services.obs.removeObserver(this, "weave:service:login:finish"); Services.obs.removeObserver(this, "weave:engine:sync:finish"); + + Services.obs.removeObserver(this, "cloudsync:tabs:update"); }, - buildList: function(force) { - if (!Weave.Service.isLoggedIn || !this._refetchTabs(force)) - return; - //XXXzpao We should say something about not being logged in & not having data - // or tell the appropriate condition. (bug 583344) - - this._generateTabList(); - }, - - createItem: function(attrs) { + createItem: function (attrs) { let item = document.createElement("richlistitem"); - // Copy the attributes from the argument into the item - for (let attr in attrs) + // Copy the attributes from the argument into the item. + for (let attr in attrs) { item.setAttribute(attr, attrs[attr]); + } - if (attrs["type"] == "tab") + if (attrs["type"] == "tab") { item.label = attrs.title != "" ? attrs.title : attrs.url; + } return item; }, - filterTabs: function(event) { + filterTabs: function (event) { let val = event.target.value.toLowerCase(); let numTabs = this._tabsList.getRowCount(); let clientTabs = 0; let currentClient = null; - for (let i = 0;i < numTabs;i++) { + + for (let i = 0; i < numTabs; i++) { let item = this._tabsList.getItemAtIndex(i); let hide = false; if (item.getAttribute("type") == "tab") { - if (!item.getAttribute("url").toLowerCase().contains(val) && - !item.getAttribute("title").toLowerCase().contains(val)) + if (!item.getAttribute("url").toLowerCase().contains(val) && + !item.getAttribute("title").toLowerCase().contains(val)) { hide = true; - else + } else { clientTabs++; + } } else if (item.getAttribute("type") == "client") { if (currentClient) { - if (clientTabs == 0) + if (clientTabs == 0) { currentClient.hidden = true; + } } currentClient = item; clientTabs = 0; } item.hidden = hide; } - if (clientTabs == 0) + if (clientTabs == 0) { currentClient.hidden = true; + } }, - openSelected: function() { + openSelected: function () { let items = this._tabsList.selectedItems; let urls = []; - for (let i = 0;i < items.length;i++) { + for (let i = 0; i < items.length; i++) { if (items[i].getAttribute("type") == "tab") { urls.push(items[i].getAttribute("url")); let index = this._tabsList.getIndexOfItem(items[i]); @@ -93,7 +106,7 @@ let RemoteTabViewer = { } }, - bookmarkSingleTab: function() { + bookmarkSingleTab: function () { let item = this._tabsList.selectedItems[0]; let uri = Weave.Utils.makeURI(item.getAttribute("url")); let title = item.getAttribute("title"); @@ -108,14 +121,15 @@ let RemoteTabViewer = { }, window.top); }, - bookmarkSelectedTabs: function() { + bookmarkSelectedTabs: function () { let items = this._tabsList.selectedItems; let URIs = []; - for (let i = 0;i < items.length;i++) { + for (let i = 0; i < items.length; i++) { if (items[i].getAttribute("type") == "tab") { let uri = Weave.Utils.makeURI(items[i].getAttribute("url")); - if (!uri) + if (!uri) { continue; + } URIs.push(uri); } @@ -133,7 +147,7 @@ let RemoteTabViewer = { try { let iconURI = Weave.Utils.makeURI(iconUri); return PlacesUtils.favicons.getFaviconLinkForIcon(iconURI).spec; - } catch(ex) { + } catch (ex) { // Do nothing. } @@ -141,16 +155,58 @@ let RemoteTabViewer = { return defaultIcon || PlacesUtils.favicons.defaultFavicon.spec; }, - _generateTabList: function() { - let engine = Weave.Service.engineManager.get("tabs"); + _waitingForBuildList: false, + + _buildListRequested: false, + + buildList: function (force) { + if (this._waitingForBuildList) { + this._buildListRequested = true; + return; + } + + this._waitingForBuildList = true; + this._buildListRequested = false; + + this._clearTabList(); + + if (Weave.Service.isLoggedIn && this._refetchTabs(force)) { + this._generateWeaveTabList(); + } else { + //XXXzpao We should say something about not being logged in & not having data + // or tell the appropriate condition. (bug 583344) + } + + function complete() { + this._waitingForBuildList = false; + if (this._buildListRequested) { + CommonUtils.nextTick(this.buildList, this); + } + } + + if (CloudSync && CloudSync.ready && CloudSync().tabsReady && CloudSync().tabs.hasRemoteTabs()) { + this._generateCloudSyncTabList() + .then(complete, complete); + } else { + complete(); + } + }, + + _clearTabList: function () { let list = this._tabsList; - // clear out existing richlistitems + // Clear out existing richlistitems. let count = list.getRowCount(); if (count > 0) { - for (let i = count - 1; i >= 0; i--) + for (let i = count - 1; i >= 0; i--) { list.removeItemAt(i); + } } + }, + + _generateWeaveTabList: function () { + let engine = Weave.Service.engineManager.get("tabs"); + let list = this._tabsList; let seenURLs = new Set(); let localURLs = engine.getOpenURLs(); @@ -189,7 +245,37 @@ let RemoteTabViewer = { } }, - adjustContextMenu: function(event) { + _generateCloudSyncTabList: function () { + let updateTabList = function (remoteTabs) { + let list = this._tabsList; + + for each (let client in remoteTabs) { + let clientAttrs = { + type: "client", + clientName: client.name, + }; + + let clientEnt = this.createItem(clientAttrs); + list.appendChild(clientEnt); + + for (let tab of client.tabs) { + let tabAttrs = { + type: "tab", + title: tab.title, + url: tab.url, + icon: this.getIcon(tab.icon), + }; + let tabEnt = this.createItem(tabAttrs); + list.appendChild(tabEnt); + } + } + }.bind(this); + + return CloudSync().tabs.getRemoteTabs() + .then(updateTabList, Promise.reject); + }, + + adjustContextMenu: function (event) { let mode = "all"; switch (this._tabsList.selectedItems.length) { case 0: @@ -201,33 +287,40 @@ let RemoteTabViewer = { mode = "multiple"; break; } + let menu = document.getElementById("tabListContext"); let el = menu.firstChild; while (el) { let showFor = el.getAttribute("showFor"); - if (showFor) + if (showFor) { el.hidden = showFor != mode && showFor != "all"; + } el = el.nextSibling; } }, - _refetchTabs: function(force) { + _refetchTabs: function (force) { if (!force) { // Don't bother refetching tabs if we already did so recently let lastFetch = 0; try { lastFetch = Services.prefs.getIntPref("services.sync.lastTabFetch"); } - catch (e) { /* Just use the default value of 0 */ } + catch (e) { + /* Just use the default value of 0 */ + } + let now = Math.floor(Date.now() / 1000); - if (now - lastFetch < 30) + if (now - lastFetch < 30) { return false; + } } - // if Clients hasn't synced yet this session, need to sync it as well - if (Weave.Service.clientsEngine.lastSync == 0) + // if Clients hasn't synced yet this session, we need to sync it as well. + if (Weave.Service.clientsEngine.lastSync == 0) { Weave.Service.clientsEngine.sync(); + } // Force a sync only for the tabs engine let engine = Weave.Service.engineManager.get("tabs"); @@ -239,21 +332,26 @@ let RemoteTabViewer = { return true; }, - observe: function(subject, topic, data) { + observe: function (subject, topic, data) { switch (topic) { case "weave:service:login:finish": this.buildList(true); break; case "weave:engine:sync:finish": - if (subject == "tabs") - this._generateTabList(); + if (subject == "tabs") { + this.buildList(false); + } + break; + case "cloudsync:tabs:update": + this.buildList(false); break; } }, - handleClick: function(event) { - if (event.target.getAttribute("type") != "tab") + handleClick: function (event) { + if (event.target.getAttribute("type") != "tab") { return; + } if (event.button == 1) { let url = event.target.getAttribute("url"); diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 2c1af22e9b1..741baa911d1 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -372,6 +372,16 @@ + + + + + + + @@ -388,7 +398,9 @@ } for (let i = 0; i < this.browsers.length; i++) { - if (this.browsers[i].contentWindow == aWindow) + // NB: We use contentWindowAsCPOW so that this code works both + // for remote browsers as well. aWindow may be a CPOW. + if (this.browsers[i].contentWindowAsCPOW == aWindow) return this.tabs[i]; } return null; diff --git a/browser/base/content/test/general/browser_searchSuggestionUI.js b/browser/base/content/test/general/browser_searchSuggestionUI.js index f38de4c8076..d5afd06b334 100644 --- a/browser/base/content/test/general/browser_searchSuggestionUI.js +++ b/browser/base/content/test/general/browser_searchSuggestionUI.js @@ -143,6 +143,7 @@ add_task(function* formHistory() { let deferred = Promise.defer(); Services.obs.addObserver(function onAdd(subj, topic, data) { if (data == "formhistory-add") { + Services.obs.removeObserver(onAdd, "satchel-storage-changed"); executeSoon(() => deferred.resolve()); } }, "satchel-storage-changed", false); @@ -167,8 +168,9 @@ add_task(function* formHistory() { // Wait for Satchel. deferred = Promise.defer(); - Services.obs.addObserver(function onAdd(subj, topic, data) { + Services.obs.addObserver(function onRemove(subj, topic, data) { if (data == "formhistory-remove") { + Services.obs.removeObserver(onRemove, "satchel-storage-changed"); executeSoon(() => deferred.resolve()); } }, "satchel-storage-changed", false); diff --git a/browser/base/jar.mn b/browser/base/jar.mn index 9aee2941027..373b196b342 100644 --- a/browser/base/jar.mn +++ b/browser/base/jar.mn @@ -46,9 +46,7 @@ browser.jar: content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png) content/browser/abouthome/mozilla@2x.png (content/abouthome/mozilla@2x.png) - content/browser/aboutneterror/netError.xhtml (content/aboutneterror/netError.xhtml) - content/browser/aboutneterror/netError.css (content/aboutneterror/netError.css) - content/browser/aboutneterror/info.svg (content/aboutneterror/info.svg) + content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml) #ifdef MOZ_SERVICES_HEALTHREPORT content/browser/abouthealthreport/abouthealth.xhtml (content/abouthealthreport/abouthealth.xhtml) @@ -111,7 +109,7 @@ browser.jar: content/browser/pageinfo/security.js (content/pageinfo/security.js) #ifdef MOZ_SERVICES_SYNC content/browser/sync/aboutSyncTabs.xul (content/sync/aboutSyncTabs.xul) - content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js) +* content/browser/sync/aboutSyncTabs.js (content/sync/aboutSyncTabs.js) content/browser/sync/aboutSyncTabs.css (content/sync/aboutSyncTabs.css) content/browser/sync/aboutSyncTabs-bindings.xml (content/sync/aboutSyncTabs-bindings.xml) * content/browser/sync/setup.xul (content/sync/setup.xul) @@ -175,4 +173,4 @@ browser.jar: % overlay chrome://browser/content/browser.xul chrome://browser/content/report-phishing-overlay.xul #endif -% override chrome://global/content/netError.xhtml chrome://browser/content/aboutneterror/netError.xhtml +% override chrome://global/content/netError.xhtml chrome://browser/content/aboutNetError.xhtml diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm index 268a6e49089..85727b90afc 100644 --- a/browser/components/customizableui/CustomizableUI.jsm +++ b/browser/components/customizableui/CustomizableUI.jsm @@ -1845,12 +1845,25 @@ let CustomizableUIInternal = { if (gInBatchStack || !gDirty) { return; } - let state = { placements: gPlacements, + // Clone because we want to modify this map: + let state = { placements: new Map(gPlacements), seen: gSeenWidgets, dirtyAreaCache: gDirtyAreaCache, currentVersion: kVersion, newElementCount: gNewElementCount }; + // Merge in previously saved areas if not present in gPlacements. + // This way, state is still persisted for e.g. temporarily disabled + // add-ons - see bug 989338. + if (gSavedState && gSavedState.placements) { + for (let area of Object.keys(gSavedState.placements)) { + if (!state.placements.has(area)) { + let placements = gSavedState.placements[area]; + state.placements.set(area, placements); + } + } + } + LOG("Saving state."); let serialized = JSON.stringify(state, this.serializerHelper); LOG("State saved as: " + serialized); diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini index 2838ce287f2..5c4721df215 100644 --- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -104,6 +104,7 @@ skip-if = os == "linux" [browser_985815_propagate_setToolbarVisibility.js] [browser_981305_separator_insertion.js] [browser_988072_sidebar_events.js] +[browser_989338_saved_placements_not_resaved.js] [browser_989751_subviewbutton_class.js] [browser_987177_destroyWidget_xul.js] [browser_987177_xul_wrapper_updating.js] diff --git a/browser/components/customizableui/test/browser_989338_saved_placements_not_resaved.js b/browser/components/customizableui/test/browser_989338_saved_placements_not_resaved.js new file mode 100644 index 00000000000..61c3567f5f4 --- /dev/null +++ b/browser/components/customizableui/test/browser_989338_saved_placements_not_resaved.js @@ -0,0 +1,56 @@ +/* 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/. */ + +"use strict"; + +const BUTTONID = "test-widget-saved-earlier"; +const AREAID = "test-area-saved-earlier"; + +let hadSavedState; +function test() { + // Hack our way into the module to fake a saved state that isn't there... + let backstagePass = Cu.import("resource:///modules/CustomizableUI.jsm", {}); + hadSavedState = backstagePass.gSavedState != null; + if (!hadSavedState) { + backstagePass.gSavedState = {placements: {}}; + } + backstagePass.gSavedState.placements[AREAID] = [BUTTONID]; + // Put bogus stuff in the saved state for the nav-bar, so as to check the current placements + // override this one... + backstagePass.gSavedState.placements[CustomizableUI.AREA_NAVBAR] = ["bogus-navbar-item"]; + + backstagePass.gDirty = true; + backstagePass.CustomizableUIInternal.saveState(); + + let newSavedState = JSON.parse(Services.prefs.getCharPref("browser.uiCustomization.state")); + let savedArea = Array.isArray(newSavedState.placements[AREAID]); + ok(savedArea, "Should have re-saved the state, even though the area isn't registered"); + + if (savedArea) { + placementArraysEqual(AREAID, newSavedState.placements[AREAID], [BUTTONID]); + } + ok(!backstagePass.gPlacements.has(AREAID), "Placements map shouldn't have been affected"); + + let savedNavbar = Array.isArray(newSavedState.placements[CustomizableUI.AREA_NAVBAR]); + ok(savedNavbar, "Should have saved nav-bar contents"); + if (savedNavbar) { + placementArraysEqual(CustomizableUI.AREA_NAVBAR, newSavedState.placements[CustomizableUI.AREA_NAVBAR], + CustomizableUI.getWidgetIdsInArea(CustomizableUI.AREA_NAVBAR)); + } +}; + +registerCleanupFunction(function() { + let backstagePass = Cu.import("resource:///modules/CustomizableUI.jsm", {}); + if (!hadSavedState) { + backstagePass.gSavedState = null; + } else { + let savedPlacements = backstagePass.gSavedState.placements; + delete savedPlacements[AREAID]; + let realNavBarPlacements = CustomizableUI.getWidgetIdsInArea(CustomizableUI.AREA_NAVBAR); + savedPlacements[CustomizableUI.AREA_NAVBAR] = realNavBarPlacements; + } + backstagePass.gDirty = true; + backstagePass.CustomizableUIInternal.saveState(); +}); + diff --git a/browser/components/places/PlacesUIUtils.jsm b/browser/components/places/PlacesUIUtils.jsm index 842f549e034..9dd52ab31df 100644 --- a/browser/components/places/PlacesUIUtils.jsm +++ b/browser/components/places/PlacesUIUtils.jsm @@ -19,6 +19,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); +#ifdef MOZ_SERVICES_CLOUDSYNC +XPCOMUtils.defineLazyModuleGetter(this, "CloudSync", + "resource://gre/modules/CloudSync.jsm"); +#else +let CloudSync = null; +#endif + #ifdef MOZ_SERVICES_SYNC XPCOMUtils.defineLazyModuleGetter(this, "Weave", "resource://services-sync/main.js"); @@ -569,7 +576,7 @@ this.PlacesUIUtils = { var uriList = PlacesUtils.toISupportsString(urls.join("|")); var args = Cc["@mozilla.org/supports-array;1"]. createInstance(Ci.nsISupportsArray); - args.AppendElement(uriList); + args.AppendElement(uriList); browserWindow = Services.ww.openWindow(aWindow, "chrome://browser/content/browser.xul", null, "chrome,dialog=no,all", args); @@ -1002,17 +1009,18 @@ this.PlacesUIUtils = { }, shouldShowTabsFromOtherComputersMenuitem: function() { - // If Sync isn't configured yet, then don't show the menuitem. - return Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED && - Weave.Svc.Prefs.get("firstSync", "") != "notReady"; + let weaveOK = Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED && + Weave.Svc.Prefs.get("firstSync", "") != "notReady"; + let cloudSyncOK = CloudSync && CloudSync.ready && CloudSync().tabsReady && CloudSync().tabs.hasRemoteTabs(); + return weaveOK || cloudSyncOK; }, shouldEnableTabsFromOtherComputersMenuitem: function() { - // The tabs engine might never be inited (if services.sync.registerEngines - // is modified), so make sure we avoid undefined errors. - return Weave.Service.isLoggedIn && - Weave.Service.engineManager.get("tabs") && - Weave.Service.engineManager.get("tabs").enabled; + let weaveEnabled = Weave.Service.isLoggedIn && + Weave.Service.engineManager.get("tabs") && + Weave.Service.engineManager.get("tabs").enabled; + let cloudSyncEnabled = CloudSync && CloudSync.ready && CloudSync().tabsReady && CloudSync().tabs.hasRemoteTabs(); + return weaveEnabled || cloudSyncEnabled; }, }; diff --git a/browser/components/places/content/history-panel.js b/browser/components/places/content/history-panel.js index f12f360b737..bb8f63ada4b 100644 --- a/browser/components/places/content/history-panel.js +++ b/browser/components/places/content/history-panel.js @@ -3,6 +3,8 @@ * 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/. */ +Components.utils.import("resource://gre/modules/TelemetryStopwatch.jsm"); + var gHistoryTree; var gSearchBox; var gHistoryGrouping = ""; @@ -79,10 +81,16 @@ function searchHistory(aInput) options.resultType = resultType; options.includeHidden = !!aInput; + if (gHistoryGrouping == "lastvisited") + this.TelemetryStopwatch.start("HISTORY_LASTVISITED_TREE_QUERY_TIME_MS"); + // call load() on the tree manually // instead of setting the place attribute in history-panel.xul // otherwise, we will end up calling load() twice gHistoryTree.load([query], options); + + if (gHistoryGrouping == "lastvisited") + this.TelemetryStopwatch.finish("HISTORY_LASTVISITED_TREE_QUERY_TIME_MS"); } window.addEventListener("SidebarFocused", diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 3df96b063f5..6fcc5ad4b12 100644 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/TelemetryStopwatch.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "MigrationUtils", "resource:///modules/MigrationUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Task", @@ -16,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils", "resource://gre/modules/DownloadUtils.jsm"); const RESTORE_FILEPICKER_FILTER_EXT = "*.json;*.jsonlz4"; +const HISTORY_LIBRARY_SEARCH_TELEMETRY = "PLACES_HISTORY_LIBRARY_SEARCH_TIME_MS"; var PlacesOrganizer = { _places: null, @@ -855,7 +857,9 @@ var PlacesSearchBox = { currentView.load([query], options); } else { + TelemetryStopwatch.start(HISTORY_LIBRARY_SEARCH_TELEMETRY); currentView.applyFilter(filterString, null, true); + TelemetryStopwatch.finish(HISTORY_LIBRARY_SEARCH_TELEMETRY); } break; case "downloads": diff --git a/browser/components/preferences/advanced.js b/browser/components/preferences/advanced.js index c196cdc75ef..702c2a3ba8c 100644 --- a/browser/components/preferences/advanced.js +++ b/browser/components/preferences/advanced.js @@ -659,7 +659,7 @@ var gAdvancedPane = { } try { const DRIVE_FIXED = 3; - const LPCWSTR = ctypes.jschar.ptr; + const LPCWSTR = ctypes.char16_t.ptr; const UINT = ctypes.uint32_t; let kernel32 = ctypes.open("kernel32"); let GetDriveType = kernel32.declare("GetDriveTypeW", ctypes.default_abi, UINT, LPCWSTR); diff --git a/browser/components/preferences/tests/browser_cookies_exceptions.js b/browser/components/preferences/tests/browser_cookies_exceptions.js index c47c7fc3dbb..38d4ae69437 100644 --- a/browser/components/preferences/tests/browser_cookies_exceptions.js +++ b/browser/components/preferences/tests/browser_cookies_exceptions.js @@ -133,7 +133,9 @@ function windowLoad(event, win, dialog) { return; if (tests[currentTest].observances.length == 0) { - // Should fail here as we are not expecting a notification. + // Should fail here as we are not expecting a notification, but we don't. + // See bug 1063410. + return; } let permission = aSubject.QueryInterface(Ci.nsIPermission); diff --git a/browser/devtools/framework/ToolboxProcess.jsm b/browser/devtools/framework/ToolboxProcess.jsm index 9424b6679dc..1ed28e2f2d5 100644 --- a/browser/devtools/framework/ToolboxProcess.jsm +++ b/browser/devtools/framework/ToolboxProcess.jsm @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -const { classes: Cc, interfaces: Ci, utils: Cu } = Components; +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; const DBG_XUL = "chrome://browser/content/devtools/framework/toolbox-process-window.xul"; const CHROME_DEBUGGER_PROFILE_NAME = "chrome_debugger_profile"; diff --git a/browser/devtools/framework/sidebar.js b/browser/devtools/framework/sidebar.js index 3c17276eb05..073c3ae2af4 100644 --- a/browser/devtools/framework/sidebar.js +++ b/browser/devtools/framework/sidebar.js @@ -70,12 +70,16 @@ ToolSidebar.prototype = { let tab = this._tabbox.tabs.appendItem(); tab.setAttribute("label", ""); // Avoid showing "undefined" while the tab is loading + tab.setAttribute("id", "sidebar-tab-" + id); + + let onIFrameLoaded = (event) => { + let doc = event.target; + let win = doc.defaultView; + tab.setAttribute("label", doc.title); - let onIFrameLoaded = () => { - tab.setAttribute("label", iframe.contentDocument.title); iframe.removeEventListener("load", onIFrameLoaded, true); - if ("setPanel" in iframe.contentWindow) { - iframe.contentWindow.setPanel(this._toolPanel, iframe); + if ("setPanel" in win) { + win.setPanel(this._toolPanel, iframe); } this.emit(id + "-ready"); }; @@ -109,6 +113,27 @@ ToolSidebar.prototype = { this.emit("new-tab-registered", id); }, + /** + * Remove an existing tab. + */ + removeTab: function(id) { + let tab = this._tabbox.tabs.querySelector("tab#sidebar-tab-" + id); + if (!tab) { + return; + } + + tab.remove(); + + let panel = this.getTab(id); + if (panel) { + panel.remove(); + } + + this._tabs.delete(id); + + this.emit("tab-unregistered", id); + }, + /** * Select a specific tab. */ diff --git a/browser/devtools/framework/test/browser_toolbox_sidebar.js b/browser/devtools/framework/test/browser_toolbox_sidebar.js index f9ec0611179..752580da995 100644 --- a/browser/devtools/framework/test/browser_toolbox_sidebar.js +++ b/browser/devtools/framework/test/browser_toolbox_sidebar.js @@ -108,6 +108,7 @@ function test() { for (let tab of tabs) { is(tab.getAttribute("label"), label++, "Tab has the right title"); } + is(label, 4, "Found the right amount of tabs."); is(panel.sidebar._tabbox.selectedPanel, panels[0], "First tab is selected"); ok(panel.sidebar.getCurrentTabID(), "tab1", "getCurrentTabID() is correct"); @@ -119,13 +120,32 @@ function test() { panel.sidebar.hide(); is(panel.sidebar._tabbox.getAttribute("hidden"), "true", "Sidebar hidden"); is(panel.sidebar.getWindowForTab("tab1").location.href, tab1URL, "Window is accessible"); - testWidth(panel); + testRemoval(panel); }); }); panel.sidebar.select("tab2"); } + function testRemoval(panel) { + panel.sidebar.once("tab-unregistered", function(event, id) { + info(event); + registeredTabs[id] = false; + + is(id, "tab3", "The right tab must be removed"); + + let tabs = panel.sidebar._tabbox.querySelectorAll("tab"); + let panels = panel.sidebar._tabbox.querySelectorAll("tabpanel"); + + is(tabs.length, 2, "There is the right number of tabs"); + is(panels.length, 2, "There is the right number of panels"); + + testWidth(panel); + }); + + panel.sidebar.removeTab("tab3"); + } + function testWidth(panel) { let tabbox = panel.panelDoc.getElementById("sidebar"); tabbox.width = 420; diff --git a/browser/devtools/framework/toolbox.js b/browser/devtools/framework/toolbox.js index a92427e81a4..37b2208d50f 100644 --- a/browser/devtools/framework/toolbox.js +++ b/browser/devtools/framework/toolbox.js @@ -1520,7 +1520,9 @@ Toolbox.prototype = { this._telemetry.toolClosed("toolbox"); this._telemetry.destroy(); - return this._destroyer = promise.all(outstanding).then(() => { + // Finish all outstanding tasks (successfully or not) before destroying the + // target. + this._destroyer = promise.all(outstanding).then(null, console.error).then(() => { // Targets need to be notified that the toolbox is being torn down. // This is done after other destruction tasks since it may tear down // fronts and the debugger transport which earlier destroy methods may @@ -1533,7 +1535,7 @@ Toolbox.prototype = { this.highlighterUtils.release(); target.off("close", this.destroy); return target.destroy(); - }).then(() => { + }, console.error).then(() => { this.emit("destroyed"); // We need to grab a reference to win before this._host is destroyed. @@ -1552,6 +1554,20 @@ Toolbox.prototype = { .garbageCollect(); } }).then(null, console.error); + + let leakCheckObserver = ({wrappedJSObject: barrier}) => { + // Make the leak detector wait until this toolbox is properly destroyed. + barrier.client.addBlocker("DevTools: Wait until toolbox is destroyed", + this._destroyer); + }; + + let topic = "shutdown-leaks-before-check"; + Services.obs.addObserver(leakCheckObserver, topic, false); + this._destroyer.then(() => { + Services.obs.removeObserver(leakCheckObserver, topic); + }); + + return this._destroyer; }, _highlighterReady: function() { diff --git a/browser/devtools/inspector/inspector-panel.js b/browser/devtools/inspector/inspector-panel.js index db742577381..b3e343ce01c 100644 --- a/browser/devtools/inspector/inspector-panel.js +++ b/browser/devtools/inspector/inspector-panel.js @@ -736,6 +736,19 @@ InspectorPanel.prototype = { } }, + /** + * Show DOM properties + */ + showDOMProperties: function InspectorPanel_showDOMProperties() { + this._toolbox.openSplitConsole().then(() => { + let panel = this._toolbox.getPanel("webconsole"); + let jsterm = panel.hud.jsterm; + + jsterm.execute("inspect($0)"); + jsterm.focusInput(); + }); + }, + /** * Clear any pseudo-class locks applied to the current hierarchy. */ diff --git a/browser/devtools/inspector/inspector.xul b/browser/devtools/inspector/inspector.xul index dfae344d029..f4be54f26ea 100644 --- a/browser/devtools/inspector/inspector.xul +++ b/browser/devtools/inspector/inspector.xul @@ -55,6 +55,9 @@ + { }); let test = asyncTest(function* () { - let { inspector } = yield openInspectorForURL(TEST_URL); + let { inspector, toolbox } = yield openInspectorForURL(TEST_URL); yield testMenuItemSensitivity(); yield testPasteOuterHTMLMenuItemSensitivity(); yield testCopyMenuItems(); + yield testShowDOMProperties(); yield testPasteOuterHTMLMenu(); yield testDeleteNode(); yield testDeleteRootNode(); @@ -154,6 +155,27 @@ let test = asyncTest(function* () { } } + function* testShowDOMProperties() { + info("Testing 'Show DOM Properties' menu item."); + let showDOMPropertiesNode = inspector.panelDoc.getElementById("node-menu-showdomproperties"); + ok(showDOMPropertiesNode, "the popup menu has a show dom properties item"); + + let consoleOpened = toolbox.once("webconsole-ready"); + + info("Triggering 'Show DOM Properties' and waiting for inspector open"); + dispatchCommandEvent(showDOMPropertiesNode); + yield consoleOpened; + + let webconsoleUI = toolbox.getPanel("webconsole").hud.ui; + let messagesAdded = webconsoleUI.once("messages-added"); + yield messagesAdded; + + info("Checking if 'inspect($0)' was evaluated"); + ok(webconsoleUI.jsterm.history[0] === 'inspect($0)'); + + yield toolbox.toggleSplitConsole(); + } + function* testPasteOuterHTMLMenu() { info("Testing that 'Paste Outer HTML' menu item works."); clipboard.set("this was pasted"); diff --git a/browser/devtools/markupview/markup-view.css b/browser/devtools/markupview/markup-view.css index a5d7dff360d..15a3d526c7a 100644 --- a/browser/devtools/markupview/markup-view.css +++ b/browser/devtools/markupview/markup-view.css @@ -36,6 +36,9 @@ .html-editor-inner { border: solid .1px; flex: 1 1 main-size; + + /* Keep the editor away from the markup view floating scrollbars */ + -moz-margin-end: 12px; } .html-editor iframe { diff --git a/browser/devtools/shared/widgets/TableWidget.js b/browser/devtools/shared/widgets/TableWidget.js index a8ca10b3be6..cd189fdc365 100644 --- a/browser/devtools/shared/widgets/TableWidget.js +++ b/browser/devtools/shared/widgets/TableWidget.js @@ -593,7 +593,7 @@ Column.prototype = { * Selects the row at the `index` index */ selectRowAt: function(index) { - if (this.selectedRow) { + if (this.selectedRow != null) { this.cells[this.items[this.selectedRow]].toggleClass("theme-selected"); } if (index < 0) { @@ -930,7 +930,7 @@ Cell.prototype = { set value(value) { this._value = value; - if (!value) { + if (value == null) { this.label.setAttribute("value", ""); return; } diff --git a/browser/devtools/tilt/test/browser_tilt_02_notifications-tabs.js b/browser/devtools/tilt/test/browser_tilt_02_notifications-tabs.js index 435af263cf5..980a499c209 100644 --- a/browser/devtools/tilt/test/browser_tilt_02_notifications-tabs.js +++ b/browser/devtools/tilt/test/browser_tilt_02_notifications-tabs.js @@ -17,6 +17,10 @@ function notification(win, topic) { } let { notification, window } = expected.shift(); + if (Cu.isDeadWrapper(window)) { + // Sometimes we end up with a nuked window reference here :-( + return; + } is(topic, notification, "Saw the expected notification"); is(win, window, "Saw the expected window"); } diff --git a/browser/devtools/webconsole/console-output.js b/browser/devtools/webconsole/console-output.js index 681783a06b9..4dc34edefd2 100644 --- a/browser/devtools/webconsole/console-output.js +++ b/browser/devtools/webconsole/console-output.js @@ -1785,6 +1785,12 @@ Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype, this._columns["_index"] = l10n.getStr("table.index"); } + if (data.class == "Array") { + if (index == parseInt(index)) { + index = parseInt(index); + } + } + let property = ownProperties[index].value; let item = { _index: index }; @@ -1832,10 +1838,9 @@ Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype, } let rowCount = 0; - for (let index of Object.keys(entries || {})) { - let [key, value] = entries[index]; + for (let [key, value] of entries) { let item = { - _index: index, + _index: rowCount, _key: this._renderValueGrip(key, { concise: true }), _value: this._renderValueGrip(value, { concise: true }) }; @@ -1857,11 +1862,10 @@ Messages.ConsoleTable.prototype = Heritage.extend(Messages.Extended.prototype, } let rowCount = 0; - for (let index of Object.keys(entries || {})) { - let value = entries[index]; + for (let entry of entries) { let item = { - _index : index, - _value: this._renderValueGrip(value, { concise: true }) + _index : rowCount, + _value: this._renderValueGrip(entry, { concise: true }) }; this._data.push(item); diff --git a/browser/devtools/webconsole/test/browser_webconsole_output_table.js b/browser/devtools/webconsole/test/browser_webconsole_output_table.js index d1fbdd8dfcd..1d73e1fe3be 100644 --- a/browser/devtools/webconsole/test/browser_webconsole_output_table.js +++ b/browser/devtools/webconsole/test/browser_webconsole_output_table.js @@ -12,27 +12,27 @@ const TEST_DATA = [ { command: "console.table(languages1)", data: [ - { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, - { _index: "1", name: "Object", fileExtension: "\".ts\"" }, - { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + { _index: 0, name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: 1, name: "Object", fileExtension: "\".ts\"" }, + { _index: 2, name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } ], columns: { _index: "(index)", name: "name", fileExtension: "fileExtension" } }, { command: "console.table(languages1, 'name')", data: [ - { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, - { _index: "1", name: "Object", fileExtension: "\".ts\"" }, - { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + { _index: 0, name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: 1, name: "Object", fileExtension: "\".ts\"" }, + { _index: 2, name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } ], columns: { _index: "(index)", name: "name" } }, { command: "console.table(languages1, ['name'])", data: [ - { _index: "0", name: "\"JavaScript\"", fileExtension: "Array[1]" }, - { _index: "1", name: "Object", fileExtension: "\".ts\"" }, - { _index: "2", name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } + { _index: 0, name: "\"JavaScript\"", fileExtension: "Array[1]" }, + { _index: 1, name: "Object", fileExtension: "\".ts\"" }, + { _index: 2, name: "\"CoffeeScript\"", fileExtension: "\".coffee\"" } ], columns: { _index: "(index)", name: "name" } }, @@ -47,8 +47,8 @@ const TEST_DATA = [ { command: "console.table([[1, 2], [3, 4]])", data: [ - { _index: "0", 0: "1", 1: "2" }, - { _index: "1", 0: "3", 1: "4" } + { _index: 0, 0: "1", 1: "2" }, + { _index: 1, 0: "3", 1: "4" } ], columns: { _index: "(index)", 0: "0", 1: "1" } }, @@ -93,19 +93,19 @@ const TEST_DATA = [ { command: "console.table(mySet)", data: [ - { _index: "0", _value: "1" }, - { _index: "1", _value: "5" }, - { _index: "2", _value: "\"some text\"" }, - { _index: "3", _value: "null" }, - { _index: "4", _value: "undefined" } + { _index: 0, _value: "1" }, + { _index: 1, _value: "5" }, + { _index: 2, _value: "\"some text\"" }, + { _index: 3, _value: "null" }, + { _index: 4, _value: "undefined" } ], columns: { _index: "(iteration index)", _value: "Values" } }, { command: "console.table(myMap)", data: [ - { _index: "0", _key: "\"a string\"", _value: "\"value associated with 'a string'\"" }, - { _index: "1", _key: "5", _value: "\"value associated with 5\"" }, + { _index: 0, _key: "\"a string\"", _value: "\"value associated with 'a string'\"" }, + { _index: 1, _key: "5", _value: "\"value associated with 5\"" }, ], columns: { _index: "(iteration index)", _key: "Key", _value: "Values" } } diff --git a/browser/devtools/webide/themes/webide.css b/browser/devtools/webide/themes/webide.css index 4410ddbe662..09c7544a5e3 100644 --- a/browser/devtools/webide/themes/webide.css +++ b/browser/devtools/webide/themes/webide.css @@ -67,6 +67,8 @@ window.busy-determined #action-busy-undetermined { #project-panel-button { -moz-box-pack: start; + width: 150px; + max-width: 150px; } #project-panel-button > .panel-button-image { @@ -86,6 +88,7 @@ window.busy-determined #action-busy-undetermined { } #project-panel-button > .panel-button-label { + width: 150px; max-width: 150px; } diff --git a/browser/locales/en-US/chrome/browser/devtools/inspector.dtd b/browser/locales/en-US/chrome/browser/devtools/inspector.dtd index 27efa3718c8..b05ffa52b5d 100644 --- a/browser/locales/en-US/chrome/browser/devtools/inspector.dtd +++ b/browser/locales/en-US/chrome/browser/devtools/inspector.dtd @@ -22,3 +22,5 @@ + + diff --git a/browser/metro/base/content/sanitize.js b/browser/metro/base/content/sanitize.js index 94eacfee02e..aa177c7753c 100644 --- a/browser/metro/base/content/sanitize.js +++ b/browser/metro/base/content/sanitize.js @@ -134,6 +134,11 @@ Sanitizer.prototype = { for each (var host in hosts) { pwmgr.setLoginSavingEnabled(host, true); } + + // Clear site security settings + var sss = Cc["@mozilla.org/ssservice;1"] + .getService(Ci.nsISiteSecurityService); + sss.clearAll(); }, get canClear() diff --git a/browser/metro/components/LoginManagerPrompter.js b/browser/metro/components/LoginManagerPrompter.js index 0689a1702a4..f21538714fe 100644 --- a/browser/metro/components/LoginManagerPrompter.js +++ b/browser/metro/components/LoginManagerPrompter.js @@ -123,6 +123,12 @@ LoginManagerPrompter.prototype = { }, + setE10sData : function (aBrowser) { + // XXX Implement me! + throw new Error("Not Yet Implemented"); + }, + + /* * promptToSavePassword * diff --git a/browser/metro/profile/metro.js b/browser/metro/profile/metro.js index 3cb38e0f09d..d57bb276323 100644 --- a/browser/metro/profile/metro.js +++ b/browser/metro/profile/metro.js @@ -57,7 +57,7 @@ pref("apz.x_skate_size_multiplier", "2.5"); pref("apz.y_skate_size_multiplier", "2.5"); pref("apz.min_skate_speed", "10.0"); // 0 = free, 1 = standard, 2 = sticky -pref("apz.axis_lock_mode", 2); +pref("apz.axis_lock.mode", 2); pref("apz.cross_slide.enabled", true); pref("apz.subframe.enabled", true); diff --git a/browser/modules/ContentSearch.jsm b/browser/modules/ContentSearch.jsm index ebb9b0daf0e..02a1a8616ce 100644 --- a/browser/modules/ContentSearch.jsm +++ b/browser/modules/ContentSearch.jsm @@ -87,21 +87,30 @@ this.ContentSearch = { // { controller, previousFormHistoryResult }. See _onMessageGetSuggestions. _suggestionMap: new WeakMap(), + // Resolved when we finish shutting down. + _destroyedPromise: null, + init: function () { Cc["@mozilla.org/globalmessagemanager;1"]. getService(Ci.nsIMessageListenerManager). addMessageListener(INBOUND_MESSAGE, this); Services.obs.addObserver(this, "browser-search-engine-modified", false); + Services.obs.addObserver(this, "shutdown-leaks-before-check", false); }, destroy: function () { + if (this._destroyedPromise) { + return this._destroyedPromise; + } + Cc["@mozilla.org/globalmessagemanager;1"]. getService(Ci.nsIMessageListenerManager). removeMessageListener(INBOUND_MESSAGE, this); Services.obs.removeObserver(this, "browser-search-engine-modified"); + Services.obs.removeObserver(this, "shutdown-leaks-before-check"); this._eventQueue.length = 0; - return Promise.resolve(this._currentEventPromise); + return this._destroyedPromise = Promise.resolve(this._currentEventPromise); }, /** @@ -148,6 +157,10 @@ this.ContentSearch = { }); this._processEventQueue(); break; + case "shutdown-leaks-before-check": + subj.wrappedJSObject.client.addBlocker( + "ContentSearch: Wait until the service is destroyed", () => this.destroy()); + break; } }, diff --git a/browser/modules/test/browser_ContentSearch.js b/browser/modules/test/browser_ContentSearch.js index 4bee1a73499..c4629860dee 100644 --- a/browser/modules/test/browser_ContentSearch.js +++ b/browser/modules/test/browser_ContentSearch.js @@ -45,7 +45,7 @@ add_task(function* SetCurrentEngine() { info("Test observed " + data); if (data == "engine-current") { ok(true, "Test observed engine-current"); - Services.obs.removeObserver(obs, "browser-search-engine-modified", false); + Services.obs.removeObserver(obs, "browser-search-engine-modified"); deferred.resolve(); } }, "browser-search-engine-modified", false); @@ -188,6 +188,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() { let deferred = Promise.defer(); Services.obs.addObserver(function onAdd(subj, topic, data) { if (data == "formhistory-add") { + Services.obs.removeObserver(onAdd, "satchel-storage-changed"); executeSoon(() => deferred.resolve()); } }, "satchel-storage-changed", false); @@ -224,6 +225,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() { deferred = Promise.defer(); Services.obs.addObserver(function onRemove(subj, topic, data) { if (data == "formhistory-remove") { + Services.obs.removeObserver(onRemove, "satchel-storage-changed"); executeSoon(() => deferred.resolve()); } }, "satchel-storage-changed", false); diff --git a/browser/modules/test/browser_SignInToWebsite.js b/browser/modules/test/browser_SignInToWebsite.js index d562234fe47..e3a417045de 100644 --- a/browser/modules/test/browser_SignInToWebsite.js +++ b/browser/modules/test/browser_SignInToWebsite.js @@ -255,7 +255,8 @@ function test_auth() { let winObs = new WindowObserver(function(authWin) { ok(authWin, "Authentication window opened"); - ok(authWin.contentWindow.location); + // See bug 1063404. + // ok(authWin.location); }); Services.ww.registerNotification(winObs); diff --git a/browser/themes/linux/jar.mn b/browser/themes/linux/jar.mn index e60fd8d1ccb..faba4c43bbd 100644 --- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -14,6 +14,7 @@ browser.jar: skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png skin/classic/browser/aboutCertError_sectionExpanded.png skin/classic/browser/aboutNetError.css (../shared/aboutNetError.css) + skin/classic/browser/aboutNetError_info.svg (../shared/aboutNetError_info.svg) skin/classic/browser/aboutSocialError.css #ifdef MOZ_SERVICES_SYNC skin/classic/browser/aboutSyncTabs.css diff --git a/browser/themes/osx/jar.mn b/browser/themes/osx/jar.mn index ca4733382d0..25abe78e440 100644 --- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -6,6 +6,7 @@ browser.jar: % skin browser classic/1.0 %skin/classic/browser/ skin/classic/browser/sanitizeDialog.css (sanitizeDialog.css) skin/classic/browser/aboutNetError.css (../shared/aboutNetError.css) + skin/classic/browser/aboutNetError_info.svg (../shared/aboutNetError_info.svg) * skin/classic/browser/aboutSessionRestore.css (aboutSessionRestore.css) skin/classic/browser/aboutSessionRestore-window-icon.png skin/classic/browser/aboutWelcomeBack.css (../shared/aboutWelcomeBack.css) diff --git a/browser/themes/shared/aboutNetError.css b/browser/themes/shared/aboutNetError.css index 66c2acfc468..71da6fbf795 100644 --- a/browser/themes/shared/aboutNetError.css +++ b/browser/themes/shared/aboutNetError.css @@ -1 +1,69 @@ -/* This deliberately left empty for themes to use/override. */ +/* 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/. */ + +@import url("chrome://global/skin/in-content/common.css"); + +body { + display: flex; + box-sizing: padding-box; + min-height: 100vh; + padding: 0 48px; + align-items: center; + justify-content: center; +} + +ul, ol { + margin: 0; + padding: 0; + -moz-margin-start: 1em; +} + +ul > li, ol > li { + margin-bottom: .5em; +} + +ul { + list-style: disc; +} + +#errorPageContainer { + min-width: 320px; + max-width: 512px; +} + +#errorTitleText { + background: url("aboutNetError_info.svg") left 0 no-repeat; + background-size: 1.2em; + -moz-margin-start: -2em; + -moz-padding-start: 2em; +} + +#errorTitleText:-moz-dir(rtl) { + background-position: right 0; +} + +#errorTryAgain { + margin-top: 1.2em; + min-width: 150px +} + +#errorContainer { + display: none; +} + +@media (max-width: 675px) { + #errorTitleText { + padding-top: 0; + background-image: none; + -moz-padding-start: 0; + -moz-margin-start: 0; + } +} + +/* Pressing the retry button will cause the cursor to flicker from a pointer to + * not-allowed. Override the disabled cursor behaviour since we will never show + * the button disabled as the initial state. */ +button:disabled { + cursor: pointer; +} diff --git a/browser/base/content/aboutneterror/info.svg b/browser/themes/shared/aboutNetError_info.svg similarity index 100% rename from browser/base/content/aboutneterror/info.svg rename to browser/themes/shared/aboutNetError_info.svg diff --git a/browser/themes/windows/jar.mn b/browser/themes/windows/jar.mn index a9f3825ae9b..19b72ad38e6 100644 --- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -16,6 +16,7 @@ browser.jar: skin/classic/browser/aboutCertError_sectionCollapsed-rtl.png skin/classic/browser/aboutCertError_sectionExpanded.png skin/classic/browser/aboutNetError.css (../shared/aboutNetError.css) + skin/classic/browser/aboutNetError_info.svg (../shared/aboutNetError_info.svg) skin/classic/browser/aboutSocialError.css #ifdef MOZ_SERVICES_SYNC skin/classic/browser/aboutSyncTabs.css @@ -430,6 +431,7 @@ browser.jar: skin/classic/aero/browser/aboutCertError_sectionCollapsed-rtl.png skin/classic/aero/browser/aboutCertError_sectionExpanded.png skin/classic/aero/browser/aboutNetError.css (../shared/aboutNetError.css) + skin/classic/aero/browser/aboutNetError_info.svg (../shared/aboutNetError_info.svg) skin/classic/aero/browser/aboutSocialError.css #ifdef MOZ_SERVICES_SYNC skin/classic/aero/browser/aboutSyncTabs.css diff --git a/build/autoconf/android.m4 b/build/autoconf/android.m4 index 27cb924447b..8862a73b5c0 100644 --- a/build/autoconf/android.m4 +++ b/build/autoconf/android.m4 @@ -250,6 +250,45 @@ AC_SUBST([STLPORT_LIBS]) ]) +AC_DEFUN([MOZ_ANDROID_GOOGLE_PLAY_SERVICES], +[ + +if test -n "$MOZ_NATIVE_DEVICES" ; then + AC_SUBST(MOZ_NATIVE_DEVICES) + + AC_MSG_CHECKING([for google play services]) + GOOGLE_PLAY_SERVICES_LIB="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar" + GOOGLE_PLAY_SERVICES_RES="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/res" + AC_SUBST(GOOGLE_PLAY_SERVICES_LIB) + AC_SUBST(GOOGLE_PLAY_SERVICES_RES) + if ! test -e $GOOGLE_PLAY_SERVICES_LIB ; then + AC_MSG_ERROR([You must download Google Play Services to build with native video casting support enabled. Run the Android SDK tool and install Google Play Services under Extras. See http://developer.android.com/google/play-services/setup.html for more info. (looked for $GOOGLE_PLAY_SERVICES_LIB) ]) + fi + AC_MSG_RESULT([$GOOGLE_PLAY_SERVICES_LIB]) + + ANDROID_APPCOMPAT_LIB="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/libs/android-support-v7-appcompat.jar" + ANDROID_APPCOMPAT_RES="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/res" + AC_MSG_CHECKING([for v7 appcompat library]) + if ! test -e $ANDROID_APPCOMPAT_LIB ; then + AC_MSG_ERROR([You must download the v7 app compat Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_APPCOMPAT_LIB)]) + fi + AC_MSG_RESULT([$ANDROID_APPCOMPAT_LIB]) + AC_SUBST(ANDROID_APPCOMPAT_LIB) + AC_SUBST(ANDROID_APPCOMPAT_RES) + + ANDROID_MEDIAROUTER_LIB="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/libs/android-support-v7-mediarouter.jar" + ANDROID_MEDIAROUTER_RES="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/res" + AC_MSG_CHECKING([for v7 mediarouter library]) + if ! test -e $ANDROID_MEDIAROUTER_LIB ; then + AC_MSG_ERROR([You must download the v7 media router Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_MEDIAROUTER_LIB)]) + fi + AC_MSG_RESULT([$ANDROID_MEDIAROUTER_LIB]) + AC_SUBST(ANDROID_MEDIAROUTER_LIB) + AC_SUBST(ANDROID_MEDIAROUTER_RES) +fi + +]) + AC_DEFUN([MOZ_ANDROID_SDK], [ @@ -347,40 +386,6 @@ case "$target" in fi AC_MSG_RESULT([$ANDROID_COMPAT_LIB]) - if test -n "$MOZ_NATIVE_DEVICES" ; then - AC_SUBST(MOZ_NATIVE_DEVICES) - - AC_MSG_CHECKING([for google play services]) - GOOGLE_PLAY_SERVICES_LIB="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar" - GOOGLE_PLAY_SERVICES_RES="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/res" - AC_SUBST(GOOGLE_PLAY_SERVICES_LIB) - AC_SUBST(GOOGLE_PLAY_SERVICES_RES) - if ! test -e $GOOGLE_PLAY_SERVICES_LIB ; then - AC_MSG_ERROR([You must download Google Play Services to build with native video casting support enabled. Run the Android SDK tool and install Google Play Services under Extras. See http://developer.android.com/google/play-services/setup.html for more info. (looked for $GOOGLE_PLAY_SERVICES_LIB) ]) - fi - AC_MSG_RESULT([$GOOGLE_PLAY_SERVICES_LIB]) - - ANDROID_APPCOMPAT_LIB="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/libs/android-support-v7-appcompat.jar" - ANDROID_APPCOMPAT_RES="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/res" - AC_MSG_CHECKING([for v7 appcompat library]) - if ! test -e $ANDROID_APPCOMPAT_LIB ; then - AC_MSG_ERROR([You must download the v7 app compat Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_APPCOMPAT_LIB)]) - fi - AC_MSG_RESULT([$ANDROID_APPCOMPAT_LIB]) - AC_SUBST(ANDROID_APPCOMPAT_LIB) - AC_SUBST(ANDROID_APPCOMPAT_RES) - - ANDROID_MEDIAROUTER_LIB="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/libs/android-support-v7-mediarouter.jar" - ANDROID_MEDIAROUTER_RES="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/res" - AC_MSG_CHECKING([for v7 mediarouter library]) - if ! test -e $ANDROID_MEDIAROUTER_LIB ; then - AC_MSG_ERROR([You must download the v7 media router Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_MEDIAROUTER_LIB)]) - fi - AC_MSG_RESULT([$ANDROID_MEDIAROUTER_LIB]) - AC_SUBST(ANDROID_MEDIAROUTER_LIB) - AC_SUBST(ANDROID_MEDIAROUTER_RES) - fi - dnl Google has a history of moving the Android tools around. We don't dnl care where they are, so let's try to find them anywhere we can. ALL_ANDROID_TOOLS_PATHS="$ANDROID_TOOLS:$ANDROID_BUILD_TOOLS:$ANDROID_PLATFORM_TOOLS" @@ -408,6 +413,16 @@ case "$target" in ;; esac +MOZ_ARG_ENABLE_BOOL(android-resource-constrained, +[ --enable-android-resource-constrained + exclude hi-res images and similar from the final APK], + MOZ_ANDROID_RESOURCE_CONSTRAINED=1) + +if test -n "$MOZ_ANDROID_RESOURCE_CONSTRAINED"; then + AC_DEFINE(MOZ_ANDROID_RESOURCE_CONSTRAINED, $MOZ_ANDROID_RESOURCE_CONSTRAINED) + AC_SUBST(MOZ_ANDROID_RESOURCE_CONSTRAINED) +fi + MOZ_ARG_WITH_STRING(android-min-sdk, [ --with-android-min-sdk=[VER] Impose a minimum Firefox for Android SDK version], [ MOZ_ANDROID_MIN_SDK_VERSION=$withval ]) @@ -428,10 +443,12 @@ if test -n "$MOZ_ANDROID_MIN_SDK_VERSION"; then fi AC_DEFINE_UNQUOTED(MOZ_ANDROID_MIN_SDK_VERSION, $MOZ_ANDROID_MIN_SDK_VERSION) + AC_SUBST(MOZ_ANDROID_MIN_SDK_VERSION) fi if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then AC_DEFINE_UNQUOTED(MOZ_ANDROID_MAX_SDK_VERSION, $MOZ_ANDROID_MAX_SDK_VERSION) + AC_SUBST(MOZ_ANDROID_MAX_SDK_VERSION) fi ]) diff --git a/build/automation.py.in b/build/automation.py.in index d3cfa972632..ac4fa28a239 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -684,7 +684,7 @@ class Automation(object): import fix_stack_using_bpsyms as stackFixerModule stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line, symbolsPath) del sys.path[0] - elif self.IS_DEBUG_BUILD and self.IS_MAC and False: + elif self.IS_DEBUG_BUILD and self.IS_MAC: # Run each line through a function in fix_macosx_stack.py (uses atos) sys.path.insert(0, utilityPath) import fix_macosx_stack as stackFixerModule diff --git a/build/mobile/remoteautomation.py b/build/mobile/remoteautomation.py index 1bee7668e7f..59806cefdfd 100644 --- a/build/mobile/remoteautomation.py +++ b/build/mobile/remoteautomation.py @@ -126,7 +126,8 @@ class RemoteAutomation(Automation): self.deleteANRs() except DMError: print "Error pulling %s" % traces - pass + except IOError: + print "Error pulling %s" % traces else: print "%s not found" % traces diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index c2825ffac72..e85c9f89dd8 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -33,6 +33,7 @@ #include "nsTextFormatter.h" #include "nsIStringBundle.h" #include "nsNetUtil.h" +#include "nsIEffectiveTLDService.h" #include "nsIProperties.h" #include "nsDirectoryServiceDefs.h" #include "nsIFile.h" @@ -580,6 +581,35 @@ DenyAccessIfURIHasFlags(nsIURI* aURI, uint32_t aURIFlags) return NS_OK; } +static bool +EqualOrSubdomain(nsIURI* aProbeArg, nsIURI* aBase) +{ + // Make a clone of the incoming URI, because we're going to mutate it. + nsCOMPtr probe; + nsresult rv = aProbeArg->Clone(getter_AddRefs(probe)); + NS_ENSURE_SUCCESS(rv, false); + + nsCOMPtr tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); + NS_ENSURE_TRUE(tldService, false); + while (true) { + if (nsScriptSecurityManager::SecurityCompareURIs(probe, aBase)) { + return true; + } + + nsAutoCString host, newHost; + nsresult rv = probe->GetHost(host); + NS_ENSURE_SUCCESS(rv, false); + + rv = tldService->GetNextSubDomain(host, newHost); + if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) { + return false; + } + NS_ENSURE_SUCCESS(rv, false); + rv = probe->SetHost(newHost); + NS_ENSURE_SUCCESS(rv, false); + } +} + NS_IMETHODIMP nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal, nsIURI *aTargetURI, @@ -796,7 +826,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal, // Allow domains that were whitelisted in the prefs. In 99.9% of cases, // this array is empty. for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) { - if (SecurityCompareURIs(mFileURIWhitelist[i], sourceURI)) { + if (EqualOrSubdomain(sourceURI, mFileURIWhitelist[i])) { return NS_OK; } } @@ -1426,7 +1456,15 @@ nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList) { // Grab the current site. bound = SkipUntil(aSiteList, base); - auto site = Substring(aSiteList, base, bound - base); + nsAutoCString site(Substring(aSiteList, base, bound - base)); + + // Check if the URI is schemeless. If so, add both http and https. + nsAutoCString unused; + if (NS_FAILED(sIOService->ExtractScheme(site, unused))) { + AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("http://") + site); + AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site); + continue; + } // Convert it to a URI and add it to our list. nsCOMPtr uri; diff --git a/caps/tests/mochitest/test_bug995943.xul b/caps/tests/mochitest/test_bug995943.xul index d6554d523e9..29d715f1eeb 100644 --- a/caps/tests/mochitest/test_bug995943.xul +++ b/caps/tests/mochitest/test_bug995943.xul @@ -82,11 +82,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943 pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '], ['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'], ['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'], - ['capability.policy.somepolicy.sites', ' http://example.org https://example.com'], + ['capability.policy.somepolicy.sites', ' http://example.org test1.example.com https://test2.example.com '], ['capability.policy.someotherpolicy.sites', 'http://example.net ']])) .then(checkLoadFileURI.bind(null, 'http://example.org', true)) - .then(checkLoadFileURI.bind(null, 'http://example.com', false)) + .then(checkLoadFileURI.bind(null, 'http://test2.example.com', false)) + .then(checkLoadFileURI.bind(null, 'https://test2.example.com', true)) + .then(checkLoadFileURI.bind(null, 'http://sub1.test2.example.com', false)) + .then(checkLoadFileURI.bind(null, 'https://sub1.test2.example.com', true)) .then(checkLoadFileURI.bind(null, 'http://example.net', false)) + .then(checkLoadFileURI.bind(null, 'http://test1.example.com', true)) + .then(checkLoadFileURI.bind(null, 'https://test1.example.com', true)) + .then(checkLoadFileURI.bind(null, 'http://sub1.test1.example.com', true)) + .then(checkLoadFileURI.bind(null, 'https://sub1.test1.example.com', true)) .then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']])) .then(checkLoadFileURI.bind(null, 'http://example.net', true)) .then(popPrefs) diff --git a/config/check_spidermonkey_style.py b/config/check_spidermonkey_style.py index d5956280a37..8aa5150eb32 100644 --- a/config/check_spidermonkey_style.py +++ b/config/check_spidermonkey_style.py @@ -399,6 +399,10 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname # Extract the #include statements as a tree of IBlocks and IIncludes. for linenum, line in enumerate(f, start=1): + # We're only interested in lines that contain a '#'. + if not '#' in line: + continue + # Look for a |#include "..."| line. m = re.match(r'\s*#\s*include\s+"([^"]*)"', line) if m is not None: @@ -482,16 +486,12 @@ def do_file(filename, inclname, file_kind, f, all_inclnames, included_h_inclname error(filename, str(include1.linenum) + ':' + str(include2.linenum), include1.quote() + ' should be included after ' + include2.quote()) - # The #include statements in the files in assembler/ have all manner of implicit - # ordering requirements. Boo. Ignore them. - skip_order_checking = inclname.startswith('assembler/') - # Check the extracted #include statements, both individually, and the ordering of # adjacent pairs that live in the same block. def pair_traverse(prev, this): if this.isLeaf(): check_include_statement(this) - if prev is not None and prev.isLeaf() and not skip_order_checking: + if prev is not None and prev.isLeaf(): check_includes_order(prev, this) else: for prev2, this2 in zip([None] + this.kids[0:-1], this.kids): diff --git a/config/config.mk b/config/config.mk index c91db9a154e..1d1e9c29da2 100644 --- a/config/config.mk +++ b/config/config.mk @@ -255,19 +255,6 @@ endif # _ENABLE_PIC=1 -# Determine if module being compiled is destined -# to be merged into libxul - -ifneq (,$(filter xul xul-%,$(FINAL_LIBRARY) $(LIBRARY_NAME))) - LIBXUL_LIBRARY := 1 -endif - -ifdef LIBXUL_LIBRARY -ifdef IS_COMPONENT -$(error IS_COMPONENT is set, but is not compatible with LIBXUL_LIBRARY) -endif -endif - # PGO on MSVC is opt-in ifdef _MSC_VER ifndef MSVC_ENABLE_PGO @@ -316,22 +303,6 @@ ifdef _MSC_VER OS_LDFLAGS += $(DELAYLOAD_LDFLAGS) endif # _MSC_VER -ifneq (,$(LIBXUL_LIBRARY)) -DEFINES += -DMOZILLA_INTERNAL_API -endif - -# Force XPCOM/widget/gfx methods to be _declspec(dllexport) when we're -# building libxul libraries -ifdef LIBXUL_LIBRARY -DEFINES += \ - -DIMPL_LIBXUL \ - $(NULL) - -ifndef JS_SHARED_LIBRARY -DEFINES += -DSTATIC_EXPORTABLE_JS_API -endif -endif - MAKE_JARS_FLAGS = \ -t $(topsrcdir) \ -f $(MOZ_CHROME_FILE_FORMAT) \ diff --git a/config/external/nss/nss.def b/config/external/nss/nss.def index 991b7f423f1..a5d3653122d 100644 --- a/config/external/nss/nss.def +++ b/config/external/nss/nss.def @@ -491,6 +491,7 @@ SECITEM_CompareItem SECITEM_CompareItem_Util SECITEM_CopyItem SECITEM_CopyItem_Util +SECITEM_DupArray SECITEM_DupItem SECITEM_DupItem_Util SECITEM_FreeItem diff --git a/configure.in b/configure.in index baf69885373..adccfd95592 100644 --- a/configure.in +++ b/configure.in @@ -4599,6 +4599,14 @@ AC_DEFINE_UNQUOTED(MOZ_DISTRIBUTION_ID,"$MOZ_DISTRIBUTION_ID") AC_SUBST(MOZ_DISTRIBUTION_ID) +dnl ======================================================== +dnl Google Play Services, placed here so it can depend on +dnl values set by configure.sh above. +dnl ======================================================== + +MOZ_ANDROID_GOOGLE_PLAY_SERVICES + + dnl ======================================================== dnl = Pango dnl ======================================================== @@ -5631,7 +5639,7 @@ if test -n "${JAVA_BIN_PATH}" -o \ AC_MSG_ERROR([The program keytool was not found. Set \$JAVA_HOME to your Java SDK directory or use --with-java-bin-path={java-bin-dir}]) fi - AC_MSG_CHECKING([for minimum required javac version = 1.7]) + AC_MSG_CHECKING([for minimum required javac version >= 1.7]) dnl Javac spits out something like `javac 1.7.0`. This line cuts off the 'javac' _javac_version=$($JAVAC -version 2>&1 | cut -d ' ' -f 2) @@ -5645,8 +5653,8 @@ if test -n "${JAVA_BIN_PATH}" -o \ dnl Fail if we have a version other than 1.7.X if test "$_javac_major_version" -ne "1" -o \ - \( "$_javac_minor_version" -ne "7" \); then - AC_MSG_ERROR([javac 1.7 is required.]) + \( "$_javac_minor_version" -lt "7" \); then + AC_MSG_ERROR([javac 1.7 or higher is required.]) fi fi @@ -6395,10 +6403,17 @@ if test -n "$gonkdir"; then MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX fi -MOZ_ARG_ENABLE_BOOL(content-sandbox, -[ --enable-content-sandbox Enable sandboxing support for content-processes], - MOZ_CONTENT_SANDBOX=1, - MOZ_CONTENT_SANDBOX=) +case "$OS_TARGET:$NIGHTLY_BUILD" in +WINNT:1) + MOZ_CONTENT_SANDBOX=$MOZ_SANDBOX + ;; +*) + MOZ_ARG_ENABLE_BOOL(content-sandbox, + [ --enable-content-sandbox Enable sandboxing support for content-processes], + MOZ_CONTENT_SANDBOX=1, + MOZ_CONTENT_SANDBOX=) + ;; +esac if test -n "$MOZ_CONTENT_SANDBOX"; then AC_DEFINE(MOZ_CONTENT_SANDBOX) @@ -8336,6 +8351,12 @@ if test -n "$MOZ_SERVICES_SYNC"; then AC_DEFINE(MOZ_SERVICES_SYNC) fi +dnl Build Services/CloudSync if required +AC_SUBST(MOZ_SERVICES_CLOUDSYNC) +if test -n "$MOZ_SERVICES_CLOUDSYNC"; then + AC_DEFINE(MOZ_SERVICES_CLOUDSYNC) +fi + dnl Build Captive Portal Detector if required AC_SUBST(MOZ_CAPTIVEDETECT) if test -n "$MOZ_CAPTIVEDETECT"; then diff --git a/content/base/public/Element.h b/content/base/public/Element.h index bc6fd702649..d95e11af7e7 100644 --- a/content/base/public/Element.h +++ b/content/base/public/Element.h @@ -983,6 +983,62 @@ public: */ nsresult SetBoolAttr(nsIAtom* aAttr, bool aValue); + /** + * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE. + * Gets the enum value string of an attribute and using a default value if + * the attribute is missing or the string is an invalid enum value. + * + * @param aType the name of the attribute. + * @param aDefault the default value if the attribute is missing or invalid. + * @param aResult string corresponding to the value [out]. + */ + void GetEnumAttr(nsIAtom* aAttr, + const char* aDefault, + nsAString& aResult) const; + + /** + * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES. + * Gets the enum value string of an attribute and using the default missing + * value if the attribute is missing or the default invalid value if the + * string is an invalid enum value. + * + * @param aType the name of the attribute. + * @param aDefaultMissing the default value if the attribute is missing. If + null and the attribute is missing, aResult will be + set to the null DOMString; this only matters for + cases in which we're reflecting a nullable string. + * @param aDefaultInvalid the default value if the attribute is invalid. + * @param aResult string corresponding to the value [out]. + */ + void GetEnumAttr(nsIAtom* aAttr, + const char* aDefaultMissing, + const char* aDefaultInvalid, + nsAString& aResult) const; + + /** + * Unset an attribute. + */ + void UnsetAttr(nsIAtom* aAttr, ErrorResult& aError) + { + aError = UnsetAttr(kNameSpaceID_None, aAttr, true); + } + + /** + * Set an attribute in the simplest way possible. + */ + void SetAttr(nsIAtom* aAttr, const nsAString& aValue, ErrorResult& aError) + { + aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true); + } + + /** + * Set a content attribute via a reflecting nullable string IDL + * attribute (e.g. a CORS attribute). If DOMStringIsNull(aValue), + * this will actually remove the content attribute. + */ + void SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue, + ErrorResult& aError); + /** * Retrieve the ratio of font-size-inflated text font size to computed font * size for this element. This will query the element for its primary frame, diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index c302b48d33a..bafadecdd61 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -2349,8 +2349,6 @@ public: virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; } virtual mozilla::dom::SVGDocument* AsSVGDocument() { return nullptr; } - virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE; - // Each import tree has exactly one master document which is // the root of the tree, and owns the browser context. virtual already_AddRefed MasterDocument() = 0; diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index dc60324705a..3fde7ee3418 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -3107,6 +3107,50 @@ Element::SetBoolAttr(nsIAtom* aAttr, bool aValue) return UnsetAttr(kNameSpaceID_None, aAttr, true); } +void +Element::GetEnumAttr(nsIAtom* aAttr, + const char* aDefault, + nsAString& aResult) const +{ + GetEnumAttr(aAttr, aDefault, aDefault, aResult); +} + +void +Element::GetEnumAttr(nsIAtom* aAttr, + const char* aDefaultMissing, + const char* aDefaultInvalid, + nsAString& aResult) const +{ + const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr); + + aResult.Truncate(); + + if (!attrVal) { + if (aDefaultMissing) { + AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult); + } else { + SetDOMStringToNull(aResult); + } + } else { + if (attrVal->Type() == nsAttrValue::eEnum) { + attrVal->GetEnumString(aResult, true); + } else if (aDefaultInvalid) { + AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult); + } + } +} + +void +Element::SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue, + ErrorResult& aError) +{ + if (DOMStringIsNull(aValue)) { + UnsetAttr(aName, aError); + } else { + SetAttr(aName, aValue, aError); + } +} + Directionality Element::GetComputedDirectionality() const { diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 9d2ec923678..469cb783d84 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -6408,7 +6408,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern, JS::Rooted re(cx, JS_NewUCRegExpObjectNoStatics(cx, - static_cast(aPattern.BeginWriting()), + static_cast(aPattern.BeginWriting()), aPattern.Length(), 0)); if (!re) { JS_ClearPendingException(cx); @@ -6418,7 +6418,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern, JS::Rooted rval(cx, JS::NullValue()); size_t idx = 0; if (!JS_ExecuteRegExpNoStatics(cx, re, - static_cast(aValue.BeginWriting()), + static_cast(aValue.BeginWriting()), aValue.Length(), &idx, true, &rval)) { JS_ClearPendingException(cx); return true; diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index ef81e2585b0..7c114cdfedd 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -150,6 +150,9 @@ #include "nsHtml5TreeOpExecutor.h" #include "mozilla/dom/HTMLLinkElement.h" #include "mozilla/dom/HTMLMediaElement.h" +#ifdef MOZ_MEDIA_NAVIGATOR +#include "mozilla/MediaManager.h" +#endif // MOZ_MEDIA_NAVIGATOR #ifdef MOZ_WEBRTC #include "IPeerConnection.h" #endif // MOZ_WEBRTC @@ -8503,6 +8506,14 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest) return false; } +#ifdef MOZ_MEDIA_NAVIGATOR + // Check if we have active GetUserMedia use + if (MediaManager::Exists() && win && + MediaManager::Get()->IsWindowStillActive(win->WindowID())) { + return false; + } +#endif // MOZ_MEDIA_NAVIGATOR + #ifdef MOZ_WEBRTC // Check if we have active PeerConnections nsCOMPtr pcManager = @@ -12258,54 +12269,6 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode, aInResult, aResult); } -// This is just a hack around the fact that window.document is not -// [Unforgeable] yet. -JSObject* -nsIDocument::WrapObject(JSContext *aCx) -{ - MOZ_ASSERT(IsDOMBinding()); - - JS::Rooted obj(aCx, nsINode::WrapObject(aCx)); - if (!obj) { - return nullptr; - } - - nsCOMPtr win = do_QueryInterface(GetInnerWindow()); - if (!win || - static_cast(win.get())->IsDOMBinding()) { - // No window or window on new DOM binding, nothing else to do here. - return obj; - } - - if (this != win->GetExtantDoc()) { - // We're not the current document; we're also done here - return obj; - } - - JSAutoCompartment ac(aCx, obj); - - JS::Rooted winVal(aCx); - nsresult rv = nsContentUtils::WrapNative(aCx, win, &NS_GET_IID(nsIDOMWindow), - &winVal, - false); - if (NS_FAILED(rv)) { - Throw(aCx, rv); - return nullptr; - } - - NS_NAMED_LITERAL_STRING(doc_str, "document"); - - JS::Rooted winObj(aCx, &winVal.toObject()); - if (!JS_DefineUCProperty(aCx, winObj, doc_str.get(), - doc_str.Length(), obj, - JSPROP_READONLY | JSPROP_ENUMERATE, - JS_PropertyStub, JS_StrictPropertyStub)) { - return nullptr; - } - - return obj; -} - XPathEvaluator* nsIDocument::XPathEvaluator() { diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 3fb8e2cefd0..efe1658c1a4 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -64,7 +64,6 @@ #include "mozilla/MemoryReporting.h" #include "mozilla/dom/DOMImplementation.h" #include "mozilla/dom/StyleSheetList.h" -#include "nsIDOMTouchEvent.h" #include "nsDataHashtable.h" #include "mozilla/TimeStamp.h" #include "mozilla/Attributes.h" diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index b5478bc164b..a221b65f30a 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -512,7 +512,7 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle< } static bool -JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData) +JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) { nsAString* result = static_cast(aData); result->Append(static_cast(aBuf), @@ -542,7 +542,7 @@ GetParamsForMessage(JSContext* aCx, NS_ENSURE_TRUE(!json.IsEmpty(), false); JS::Rooted val(aCx, JS::NullValue()); - NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast(json.get()), + NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast(json.get()), json.Length(), &val), false); return WriteStructuredClone(aCx, val, aBuffer, aClosure); @@ -638,7 +638,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName, } JS::Rooted ret(aCx); - if (!JS_ParseJSON(aCx, static_cast(retval[i].get()), + if (!JS_ParseJSON(aCx, static_cast(retval[i].get()), retval[i].Length(), &ret)) { return NS_ERROR_UNEXPECTED; } @@ -996,7 +996,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget, } JS::Rooted jsMessage(cx, JS_NewUCStringCopyN(cx, - static_cast(aMessage.BeginReading()), + static_cast(aMessage.BeginReading()), aMessage.Length())); NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY); JS::Rooted syncv(cx, JS::BooleanValue(aIsSync)); @@ -1489,7 +1489,7 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL, nsCOMPtr input; channel->Open(getter_AddRefs(input)); nsString dataString; - jschar* dataStringBuf = nullptr; + char16_t* dataStringBuf = nullptr; size_t dataStringLength = 0; uint64_t avail64 = 0; if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) { diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index ff20540f649..657d2488d9d 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -109,7 +109,7 @@ public: bool mIsInline; // Is the script inline or loaded? bool mHasSourceMapURL; // Does the HTTP header have a source map url? nsString mSourceMapURL; // Holds source map url for loaded scripts - jschar* mScriptTextBuf; // Holds script text for non-inline scripts. Don't + char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't size_t mScriptTextLength; // use nsString so we can give ownership to jsapi. uint32_t mJSVersion; nsCOMPtr mURI; @@ -898,7 +898,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT NS_ENSURE_ARG(aRequest); nsAutoString textData; - const jschar* scriptBuf = nullptr; + const char16_t* scriptBuf = nullptr; size_t scriptLength = 0; JS::SourceBufferHolder::Ownership giveScriptOwnership = JS::SourceBufferHolder::NoOwnership; @@ -1278,7 +1278,7 @@ DetectByteOrderMark(const unsigned char* aBytes, int32_t aLen, nsCString& oChars nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData, uint32_t aLength, const nsAString& aHintCharset, nsIDocument* aDocument, - jschar*& aBufOut, size_t& aLengthOut) + char16_t*& aBufOut, size_t& aLengthOut) { if (!aLength) { aBufOut = nullptr; @@ -1335,7 +1335,7 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData, aLength, &unicodeLength); NS_ENSURE_SUCCESS(rv, rv); - aBufOut = static_cast(js_malloc(unicodeLength * sizeof(jschar))); + aBufOut = static_cast(js_malloc(unicodeLength * sizeof(char16_t))); if (!aBufOut) { aLengthOut = 0; return NS_ERROR_OUT_OF_MEMORY; diff --git a/content/base/src/nsScriptLoader.h b/content/base/src/nsScriptLoader.h index 9449d0118b6..6f5e80b76d3 100644 --- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -170,17 +170,17 @@ public: * attribute). May be the empty string. * @param aDocument Document which the data is loaded for. Must not be * null. - * @param aBufOut [out] jschar array allocated by ConvertToUTF16 and + * @param aBufOut [out] char16_t array allocated by ConvertToUTF16 and * containing data converted to unicode. Caller must * js_free() this data when no longer needed. * @param aLengthOut [out] Length of array returned in aBufOut in number - * of jschars. + * of char16_t code units. */ static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData, uint32_t aLength, const nsAString& aHintCharset, nsIDocument* aDocument, - jschar*& aBufOut, size_t& aLengthOut); + char16_t*& aBufOut, size_t& aLengthOut); /** * Processes any pending requests that are ready for processing. diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index 0791da2b707..ab087b844e0 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -766,7 +766,7 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx) // The Unicode converter has already zapped the BOM if there was one JS::Rooted value(aCx); if (!JS_ParseJSON(aCx, - static_cast(mResponseText.get()), mResponseText.Length(), + static_cast(mResponseText.get()), mResponseText.Length(), &value)) { return NS_ERROR_FAILURE; } @@ -4074,8 +4074,8 @@ ArrayBufferBuilder::mapToFileInPackage(const nsCString& aFile, return rv; } nsZipItem* zipItem = zip->GetItem(aFile.get()); - if (NS_FAILED(rv)) { - return rv; + if (!zipItem) { + return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST; } // If file was added to the package as stored(uncompressed), map to the diff --git a/content/base/test/test_bug345339.html b/content/base/test/test_bug345339.html index 92a54e80afe..4025d572e80 100644 --- a/content/base/test/test_bug345339.html +++ b/content/base/test/test_bug345339.html @@ -36,7 +36,8 @@ function afterLoad() { .getService(SpecialPowers.Ci.nsIProperties) .get("TmpD", SpecialPowers.Ci.nsILocalFile); file.append("345339_test.file"); - file.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, 0666); + // Only the file's path is used, so it doesn't need to be created. + // See also bug 1058977. filePath = file.path; SpecialPowers.wrap(iframeDoc).getElementById("file").value = filePath; diff --git a/content/html/content/public/HTMLMediaElement.h b/content/html/content/public/HTMLMediaElement.h index 4316bc271a4..923dde489e9 100755 --- a/content/html/content/public/HTMLMediaElement.h +++ b/content/html/content/public/HTMLMediaElement.h @@ -363,10 +363,16 @@ public: // XPCOM GetCurrentSrc() is OK - // XPCOM GetCrossorigin() is OK - void SetCrossOrigin(const nsAString& aValue, ErrorResult& aRv) + void GetCrossOrigin(nsAString& aResult) { - SetHTMLAttr(nsGkAtoms::crossorigin, aValue, aRv); + // Null for both missing and invalid defaults is ok, since we + // always parse to an enum value, so we don't need an invalid + // default, and we _want_ the missing default to be null. + GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult); + } + void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) + { + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); } uint16_t NetworkState() const diff --git a/content/html/content/src/HTMLImageElement.cpp b/content/html/content/src/HTMLImageElement.cpp index 4cd291120e3..19763be8513 100644 --- a/content/html/content/src/HTMLImageElement.cpp +++ b/content/html/content/src/HTMLImageElement.cpp @@ -151,11 +151,6 @@ HTMLImageElement::SetItemValueText(const nsAString& aValue) SetSrc(aValue); } -// crossorigin is not "limited to only known values" per spec, so it's -// just a string attr purposes of the DOM crossOrigin property. -// TODO: It is now (bug 880997). -NS_IMPL_STRING_ATTR(HTMLImageElement, CrossOrigin, crossorigin) - bool HTMLImageElement::Draggable() const { diff --git a/content/html/content/src/HTMLImageElement.h b/content/html/content/src/HTMLImageElement.h index bd547f5e72c..f2b2468597f 100644 --- a/content/html/content/src/HTMLImageElement.h +++ b/content/html/content/src/HTMLImageElement.h @@ -142,9 +142,16 @@ public: { SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aError); } + void GetCrossOrigin(nsAString& aResult) + { + // Null for both missing and invalid defaults is ok, since we + // always parse to an enum value, so we don't need an invalid + // default, and we _want_ the missing default to be null. + GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult); + } void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) { - SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); } void SetUseMap(const nsAString& aUseMap, ErrorResult& aError) { diff --git a/content/html/content/src/HTMLLinkElement.cpp b/content/html/content/src/HTMLLinkElement.cpp index 81a9934c870..1b03afb6864 100644 --- a/content/html/content/src/HTMLLinkElement.cpp +++ b/content/html/content/src/HTMLLinkElement.cpp @@ -117,7 +117,6 @@ NS_IMPL_STRING_ATTR(HTMLLinkElement, Rel, rel) NS_IMPL_STRING_ATTR(HTMLLinkElement, Rev, rev) NS_IMPL_STRING_ATTR(HTMLLinkElement, Target, target) NS_IMPL_STRING_ATTR(HTMLLinkElement, Type, type) -NS_IMPL_STRING_ATTR(HTMLLinkElement, CrossOrigin, crossorigin) void HTMLLinkElement::GetItemValueText(nsAString& aValue) diff --git a/content/html/content/src/HTMLLinkElement.h b/content/html/content/src/HTMLLinkElement.h index 7e278913708..a7f454360dc 100644 --- a/content/html/content/src/HTMLLinkElement.h +++ b/content/html/content/src/HTMLLinkElement.h @@ -90,10 +90,16 @@ public: { SetHTMLAttr(nsGkAtoms::href, aHref, aRv); } - // XPCOM GetCrossOrigin is fine. - void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aRv) + void GetCrossOrigin(nsAString& aResult) { - SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, aRv); + // Null for both missing and invalid defaults is ok, since we + // always parse to an enum value, so we don't need an invalid + // default, and we _want_ the missing default to be null. + GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult); + } + void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) + { + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); } // XPCOM GetRel is fine. void SetRel(const nsAString& aRel, ErrorResult& aRv) diff --git a/content/html/content/src/HTMLMediaElement.cpp b/content/html/content/src/HTMLMediaElement.cpp index b27532f7199..437f2ade7c2 100755 --- a/content/html/content/src/HTMLMediaElement.cpp +++ b/content/html/content/src/HTMLMediaElement.cpp @@ -470,7 +470,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement) // nsIDOMHTMLMediaElement NS_IMPL_URI_ATTR(HTMLMediaElement, Src, src) -NS_IMPL_STRING_ATTR(HTMLMediaElement, CrossOrigin, crossorigin) NS_IMPL_BOOL_ATTR(HTMLMediaElement, Controls, controls) NS_IMPL_BOOL_ATTR(HTMLMediaElement, Autoplay, autoplay) NS_IMPL_BOOL_ATTR(HTMLMediaElement, Loop, loop) diff --git a/content/html/content/src/HTMLScriptElement.cpp b/content/html/content/src/HTMLScriptElement.cpp index 85e52b91f57..56630f2b3b1 100644 --- a/content/html/content/src/HTMLScriptElement.cpp +++ b/content/html/content/src/HTMLScriptElement.cpp @@ -137,7 +137,6 @@ NS_IMPL_URI_ATTR(HTMLScriptElement, Src, src) NS_IMPL_STRING_ATTR(HTMLScriptElement, Type, type) NS_IMPL_STRING_ATTR(HTMLScriptElement, HtmlFor, _for) NS_IMPL_STRING_ATTR(HTMLScriptElement, Event, event) -NS_IMPL_STRING_ATTR(HTMLScriptElement, CrossOrigin, crossorigin) void HTMLScriptElement::SetCharset(const nsAString& aCharset, ErrorResult& rv) @@ -181,12 +180,6 @@ HTMLScriptElement::SetEvent(const nsAString& aEvent, ErrorResult& rv) SetHTMLAttr(nsGkAtoms::event, aEvent, rv); } -void -HTMLScriptElement::SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& rv) -{ - SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, rv); -} - nsresult HTMLScriptElement::GetAsync(bool* aValue) { diff --git a/content/html/content/src/HTMLScriptElement.h b/content/html/content/src/HTMLScriptElement.h index c301c59221d..1b89bc6114a 100644 --- a/content/html/content/src/HTMLScriptElement.h +++ b/content/html/content/src/HTMLScriptElement.h @@ -68,7 +68,17 @@ public: void SetType(const nsAString& aType, ErrorResult& rv); void SetHtmlFor(const nsAString& aHtmlFor, ErrorResult& rv); void SetEvent(const nsAString& aEvent, ErrorResult& rv); - void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& rv); + void GetCrossOrigin(nsAString& aResult) + { + // Null for both missing and invalid defaults is ok, since we + // always parse to an enum value, so we don't need an invalid + // default, and we _want_ the missing default to be null. + GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult); + } + void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) + { + SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); + } bool Async(); void SetAsync(bool aValue, ErrorResult& rv); diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 6385e9439f2..2e048a89ed8 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -347,7 +347,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect) } nsIContent* offsetParent = nullptr; - Element* docElement = GetCurrentDoc()->GetRootElement(); + Element* docElement = GetComposedDoc()->GetRootElement(); nsIContent* content = frame->GetContent(); if (content && (content->IsHTML(nsGkAtoms::body) || content == docElement)) { @@ -398,7 +398,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect) // parent chain. We want the offset parent in this case to be // the body, so we just get the body element from the document. - nsCOMPtr html_doc(do_QueryInterface(GetCurrentDoc())); + nsCOMPtr html_doc(do_QueryInterface(GetComposedDoc())); if (html_doc) { offsetParent = static_cast(html_doc.get())->GetBody(); @@ -1766,37 +1766,6 @@ nsGenericHTMLElement::GetURIListAttr(nsIAtom* aAttr, nsAString& aResult) return NS_OK; } -void -nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr, - const char* aDefault, - nsAString& aResult) const -{ - GetEnumAttr(aAttr, aDefault, aDefault, aResult); -} - -void -nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr, - const char* aDefaultMissing, - const char* aDefaultInvalid, - nsAString& aResult) const -{ - const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr); - - aResult.Truncate(); - - if (!attrVal) { - if (aDefaultMissing) { - AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult); - } - } else { - if (attrVal->Type() == nsAttrValue::eEnum) { - attrVal->GetEnumString(aResult, true); - } else if (aDefaultInvalid) { - AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult); - } - } -} - HTMLMenuElement* nsGenericHTMLElement::GetContextMenu() const { diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index d4487319c44..a5da08dce70 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -1011,11 +1011,11 @@ protected: } void SetHTMLAttr(nsIAtom* aName, const nsAString& aValue, mozilla::ErrorResult& aError) { - aError = SetAttr(kNameSpaceID_None, aName, aValue, true); + mozilla::dom::Element::SetAttr(aName, aValue, aError); } void UnsetHTMLAttr(nsIAtom* aName, mozilla::ErrorResult& aError) { - aError = UnsetAttr(kNameSpaceID_None, aName, true); + mozilla::dom::Element::UnsetAttr(aName, aError); } void SetHTMLBoolAttr(nsIAtom* aName, bool aValue, mozilla::ErrorResult& aError) { @@ -1122,35 +1122,6 @@ protected: */ nsresult GetURIListAttr(nsIAtom* aAttr, nsAString& aResult); - /** - * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE. - * Gets the enum value string of an attribute and using a default value if - * the attribute is missing or the string is an invalid enum value. - * - * @param aType the name of the attribute. - * @param aDefault the default value if the attribute is missing or invalid. - * @param aResult string corresponding to the value [out]. - */ - void GetEnumAttr(nsIAtom* aAttr, - const char* aDefault, - nsAString& aResult) const; - - /** - * Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES. - * Gets the enum value string of an attribute and using the default missing - * value if the attribute is missing or the default invalid value if the - * string is an invalid enum value. - * - * @param aType the name of the attribute. - * @param aDefaultMissing the default value if the attribute is missing. - * @param aDefaultInvalid the default value if the attribute is invalid. - * @param aResult string corresponding to the value [out]. - */ - void GetEnumAttr(nsIAtom* aAttr, - const char* aDefaultMissing, - const char* aDefaultInvalid, - nsAString& aResult) const; - /** * Locates the nsIEditor associated with this node. In general this is * equivalent to GetEditorInternal(), but for designmode or contenteditable, diff --git a/content/html/content/test/forms/chrome.ini b/content/html/content/test/forms/chrome.ini index 7cab0e5de7a..0c8fa82314c 100644 --- a/content/html/content/test/forms/chrome.ini +++ b/content/html/content/test/forms/chrome.ini @@ -1,2 +1,5 @@ [DEFAULT] +support-files = + submit_invalid_file.sjs [test_autocompleteinfo.html] +[test_submit_invalid_file.html] diff --git a/content/html/content/test/forms/mochitest.ini b/content/html/content/test/forms/mochitest.ini index f542918e148..2be29111a0a 100644 --- a/content/html/content/test/forms/mochitest.ini +++ b/content/html/content/test/forms/mochitest.ini @@ -1,7 +1,6 @@ [DEFAULT] support-files = save_restore_radio_groups.sjs - submit_invalid_file.sjs test_input_number_data.js [test_bug1039548.html] @@ -91,7 +90,6 @@ skip-if = e10s [test_step_attribute.html] skip-if = e10s [test_stepup_stepdown.html] -[test_submit_invalid_file.html] [test_textarea_attributes_reflection.html] [test_validation.html] skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support) diff --git a/content/html/content/test/forms/test_change_event.html b/content/html/content/test/forms/test_change_event.html index bf7d1510a94..3e0430dfe7a 100644 --- a/content/html/content/test/forms/test_change_event.html +++ b/content/html/content/test/forms/test_change_event.html @@ -67,7 +67,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599 function testUserInput() { //Simulating an OK click and with a file name return. - MockFilePicker.useAnyFile(); + MockFilePicker.useBlobFile(); MockFilePicker.returnValue = MockFilePicker.returnOK; var input = document.getElementById('fileInput'); input.focus(); diff --git a/content/html/content/test/forms/test_input_event.html b/content/html/content/test/forms/test_input_event.html index 4537d8fb25b..31159ae8b1e 100644 --- a/content/html/content/test/forms/test_input_event.html +++ b/content/html/content/test/forms/test_input_event.html @@ -59,7 +59,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780 function testUserInput() { // Simulating an OK click and with a file name return. - MockFilePicker.useAnyFile(); + MockFilePicker.useBlobFile(); MockFilePicker.returnValue = MockFilePicker.returnOK; var input = document.getElementById('fileInput'); input.focus(); diff --git a/content/html/content/test/forms/test_max_attribute.html b/content/html/content/test/forms/test_max_attribute.html index 5d2bf5487e3..15acb74541b 100644 --- a/content/html/content/test/forms/test_max_attribute.html +++ b/content/html/content/test/forms/test_max_attribute.html @@ -179,17 +179,12 @@ for (var test of data) { .getService(SpecialPowers.Ci.nsIProperties); var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); file.append('635499_file'); - var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(SpecialPowers.Ci.nsIFileOutputStream); - outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate - 0666, 0); - outStream.write("foo", 3); - outStream.close(); + // Only the file's path is used, so it doesn't need to be created. + // See also bug 1058977. SpecialPowers.wrap(input).value = file.path; checkValidity(input, true, apply, apply); - file.remove(false); break; case 'date': input.max = '2012-06-27'; diff --git a/content/html/content/test/forms/test_min_attribute.html b/content/html/content/test/forms/test_min_attribute.html index 473879d6631..b114ff928b1 100644 --- a/content/html/content/test/forms/test_min_attribute.html +++ b/content/html/content/test/forms/test_min_attribute.html @@ -177,17 +177,12 @@ for (var test of data) { .getService(SpecialPowers.Ci.nsIProperties); var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); file.append('635499_file'); - var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(SpecialPowers.Ci.nsIFileOutputStream); - outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate - 0666, 0); - outStream.write("foo", 3); - outStream.close(); + // Only the file's path is used, so it doesn't need to be created. + // See also bug 1058977. SpecialPowers.wrap(input).value = file.path; checkValidity(input, true, apply, apply); - file.remove(false); break; case 'date': input.value = '2012-06-28'; diff --git a/content/html/content/test/forms/test_required_attribute.html b/content/html/content/test/forms/test_required_attribute.html index 5e111844a9e..398acf2ce49 100644 --- a/content/html/content/test/forms/test_required_attribute.html +++ b/content/html/content/test/forms/test_required_attribute.html @@ -308,22 +308,18 @@ function checkInputRequiredValidityForFile() element.type = 'file' document.forms[0].appendChild(element); - function createFileWithData(fileName, fileData) { + function createFile(fileName) { var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"] .getService(SpecialPowers.Ci.nsIProperties); var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); testFile.append(fileName); - var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(SpecialPowers.Ci.nsIFileOutputStream); - outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate - 0666, 0); - outStream.write(fileData, fileData.length); - outStream.close(); + // Only the file's path is used, so it doesn't need to be created. + // See also bug 1058977. return testFile; } - var file = createFileWithData("345822_file", "file content"); + var file = createFile("345822_file"); SpecialPowers.wrap(element).value = ""; element.required = false; @@ -350,7 +346,6 @@ function checkInputRequiredValidityForFile() element.required = true; SpecialPowers.wrap(element).value = ''; - file.remove(false); document.forms[0].removeChild(element); checkSufferingFromBeingMissing(element, true); } diff --git a/content/html/content/test/forms/test_step_attribute.html b/content/html/content/test/forms/test_step_attribute.html index e692fa13d7b..2bcd21fbbfb 100644 --- a/content/html/content/test/forms/test_step_attribute.html +++ b/content/html/content/test/forms/test_step_attribute.html @@ -132,17 +132,12 @@ for (var test of data) { .getService(SpecialPowers.Ci.nsIProperties); var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile); file.append('635499_file'); - var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(SpecialPowers.Ci.nsIFileOutputStream); - outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate - 0666, 0); - outStream.write("foo", 3); - outStream.close(); + // Only the file's path is used, so it doesn't need to be created. + // See also bug 1058977. SpecialPowers.wrap(input).value = file.path; checkValidity(input, true, apply); - file.remove(false); break; case 'date': // For date, the step is calulated on the timestamp since 1970-01-01 diff --git a/content/html/content/test/forms/test_submit_invalid_file.html b/content/html/content/test/forms/test_submit_invalid_file.html index 76a7255ce7e..145d8f456e3 100644 --- a/content/html/content/test/forms/test_submit_invalid_file.html +++ b/content/html/content/test/forms/test_submit_invalid_file.html @@ -6,14 +6,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=702949 Test invalid file submission - - + + Mozilla Bug 702949