diff --git a/.hgtags b/.hgtags index 2aeaf2ede6df..048183668062 100644 --- a/.hgtags +++ b/.hgtags @@ -67,3 +67,4 @@ a95d426422816513477e5863add1b00ac7041dcb AURORA_BASE_20110412 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R14 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R14 5eb553dd2ceae5f88d80f27afc5ef3935c5d43b0 AURORA_BASE_20110705 +41b84b87c816403e1b74963d8094cff0406c989e AURORA_BASE_20110816 diff --git a/accessible/src/base/AccEvent.cpp b/accessible/src/base/AccEvent.cpp index e9ef4d01dec9..fa9f3704561e 100644 --- a/accessible/src/base/AccEvent.cpp +++ b/accessible/src/base/AccEvent.cpp @@ -136,39 +136,10 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release) //////////////////////////////////////////////////////////////////////////////// // AccEvent protected methods -nsAccessible * +nsAccessible* AccEvent::GetAccessibleForNode() const { - if (!mNode) - return nsnull; - - nsAccessible *accessible = GetAccService()->GetAccessible(mNode); - -#ifdef MOZ_XUL - // hack for xul tree table. We need a better way for firing delayed event - // against xul tree table. see bug 386821. - // There will be problem if some day we want to fire delayed event against - // the xul tree itself or an unselected treeitem. - nsCOMPtr content(do_QueryInterface(mNode)); - if (content && content->NodeInfo()->Equals(nsAccessibilityAtoms::tree, - kNameSpaceID_XUL)) { - - nsCOMPtr multiSelect = - do_QueryInterface(mNode); - - if (multiSelect) { - PRInt32 treeIndex = -1; - multiSelect->GetCurrentIndex(&treeIndex); - if (treeIndex >= 0) { - nsRefPtr treeAcc = do_QueryObject(accessible); - if (treeAcc) - return treeAcc->GetTreeItemAccessible(treeIndex); - } - } - } -#endif - - return accessible; + return mNode ? GetAccService()->GetAccessible(mNode) : nsnull; } void diff --git a/security/manager/ssl/src/nsCipherInfo.h b/accessible/src/base/Statistics.h similarity index 73% rename from security/manager/ssl/src/nsCipherInfo.h rename to accessible/src/base/Statistics.h index 7791850cae6f..06e4d0a03b7c 100644 --- a/security/manager/ssl/src/nsCipherInfo.h +++ b/accessible/src/base/Statistics.h @@ -1,3 +1,5 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -11,15 +13,15 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is Mozilla Communicator. + * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Kai Engert + * Trevor Saunders (original author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,30 +37,21 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsICipherInfo.h" -#include "nsString.h" -#include "sslt.h" +#ifndef A11Y_STATISTICS_H_ +#define A11Y_STATISTICS_H_ -class nsCipherInfoService : public nsICipherInfoService -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICIPHERINFOSERVICE +#include "mozilla/Telemetry.h" - nsCipherInfoService(); - virtual ~nsCipherInfoService(); -}; +namespace mozilla { +namespace a11y { +namespace statistics { -class nsCipherInfo : public nsICipherInfo -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICIPHERINFO + inline void A11yInitialized() + { Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED, true); } - nsCipherInfo(PRUint16 aCipherId); - virtual ~nsCipherInfo(); +} // namespace statistics +} // namespace a11y +} // namespace mozilla + +#endif -private: - PRBool mHaveInfo; - SSLCipherSuiteInfo mInfo; -}; diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index 4114cd83aeab..fb35a8283c85 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -56,6 +56,7 @@ #include "nsIAccessibilityService.h" #include "nsIAccessibleProvider.h" #include "States.h" +#include "Statistics.h" #include "nsIDOMDocument.h" #include "nsIDOMHTMLAreaElement.h" @@ -1772,6 +1773,8 @@ NS_GetAccessibilityService(nsIAccessibilityService** aResult) return NS_ERROR_FAILURE; } + statistics::A11yInitialized(); + nsAccessibilityService::gAccessibilityService = service; NS_ADDREF(*aResult = service); diff --git a/accessible/src/base/nsRootAccessible.cpp b/accessible/src/base/nsRootAccessible.cpp index 8c022db77b2b..e993dfc4e4f1 100644 --- a/accessible/src/base/nsRootAccessible.cpp +++ b/accessible/src/base/nsRootAccessible.cpp @@ -393,10 +393,10 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible* aFocusAccessible, // Coalesce focus events from the same document, because DOM focus event might // be fired for the document node and then for the focused DOM element. - focusDocument->FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS, - focusNode, - AccEvent::eCoalesceFromSameDocument, - aIsFromUserInput); + nsRefPtr focusEvent = + new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, focusAccessible, + aIsFromUserInput, AccEvent::eCoalesceFromSameDocument); + focusDocument->FireDelayedAccessibleEvent(focusEvent); } void diff --git a/accessible/src/base/nsTextAttrs.cpp b/accessible/src/base/nsTextAttrs.cpp index dd53f450c267..5ef69271e983 100644 --- a/accessible/src/base/nsTextAttrs.cpp +++ b/accessible/src/base/nsTextAttrs.cpp @@ -45,6 +45,7 @@ #include "gfxFont.h" #include "gfxUserFontSet.h" #include "nsFontMetrics.h" +#include "nsLayoutUtils.h" //////////////////////////////////////////////////////////////////////////////// // Constants and structures @@ -479,10 +480,7 @@ nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) nscoord nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame) { - nsStyleFont* styleFont = - (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font)); - - return styleFont->mSize; + return aFrame->GetStyleFont()->mSize; } @@ -527,15 +525,8 @@ nsFontWeightTextAttr::GetFontWeight(nsIFrame *aFrame) { // nsFont::width isn't suitable here because it's necessary to expose real // value of font weight (used font might not have some font weight values). - nsStyleFont* styleFont = - (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font)); - - gfxUserFontSet *fs = aFrame->PresContext()->GetUserFontSet(); - nsRefPtr fm; - aFrame->PresContext()->DeviceContext()-> - GetMetricsFor(styleFont->mFont, aFrame->GetStyleVisibility()->mLanguage, - fs, *getter_AddRefs(fm)); + nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); gfxFontGroup *fontGroup = fm->GetThebesFontGroup(); gfxFont *font = fontGroup->GetFontAt(0); diff --git a/accessible/src/msaa/nsTextAccessibleWrap.cpp b/accessible/src/msaa/nsTextAccessibleWrap.cpp index e3619d58d096..0bbda44bb15c 100644 --- a/accessible/src/msaa/nsTextAccessibleWrap.cpp +++ b/accessible/src/msaa/nsTextAccessibleWrap.cpp @@ -44,6 +44,7 @@ #include "nsIFrame.h" #include "nsFontMetrics.h" #include "nsPresContext.h" +#include "nsLayoutUtils.h" #include "gfxFont.h" @@ -256,11 +257,7 @@ __try { } nsRefPtr fm; - frame->PresContext()->DeviceContext()-> - GetMetricsFor(frame->GetStyleFont()->mFont, - frame->GetStyleVisibility()->mLanguage, - frame->PresContext()->GetUserFontSet(), - *getter_AddRefs(fm)); + nsLayoutUtils::GetFontMetricsForFrame(frame, getter_AddRefs(fm)); const nsString& name = fm->GetThebesFontGroup()->GetFontAt(0)->GetName(); if (name.IsEmpty()) diff --git a/accessible/tests/mochitest/events/Makefile.in b/accessible/tests/mochitest/events/Makefile.in index 1c099e789eaf..91326d4c399c 100644 --- a/accessible/tests/mochitest/events/Makefile.in +++ b/accessible/tests/mochitest/events/Makefile.in @@ -66,6 +66,7 @@ _TEST_FILES =\ test_focus.html \ test_focus.xul \ test_focus_name.html \ + test_focus_tree.xul \ test_focusdoc.html \ test_menu.xul \ test_mutation.html \ diff --git a/accessible/tests/mochitest/events/test_focus_tree.xul b/accessible/tests/mochitest/events/test_focus_tree.xul new file mode 100644 index 000000000000..ef979520c508 --- /dev/null +++ b/accessible/tests/mochitest/events/test_focus_tree.xul @@ -0,0 +1,120 @@ + + + + + + + + + + + + Mozilla Bug 386821 +
+

+ +
+      
+ + + + + + + + + + +
+ +
+ diff --git a/browser/Makefile.in b/browser/Makefile.in index d45b6e1a73ab..923c4d28da24 100644 --- a/browser/Makefile.in +++ b/browser/Makefile.in @@ -45,13 +45,13 @@ include $(topsrcdir)/config/config.mk PARALLEL_DIRS = \ base \ components \ - devtools \ fuel \ locales \ themes \ $(NULL) DIRS = \ + devtools \ app \ $(NULL) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 50052643c37c..86facf7900e9 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -783,12 +783,12 @@ pref("browser.sessionstore.max_windows_undo", 3); // number of crashes that can occur before the about:sessionrestore page is displayed // (this pref has no effect if more than 6 hours have passed since the last crash) pref("browser.sessionstore.max_resumed_crashes", 1); -// The number of tabs that can restore concurrently: -// < 0 = All tabs can restore at the same time -// 0 = Only the selected tab in each window will be restored -// Other tabs won't be restored until they are selected -// N = The number of tabs to restore at the same time -pref("browser.sessionstore.max_concurrent_tabs", 3); +// restore_on_demand overrides MAX_CONCURRENT_TAB_RESTORES (sessionstore constant) +// and restore_hidden_tabs. When true, tabs will not be restored until they are +// focused (also applies to tabs that aren't visible). When false, the values +// for MAX_CONCURRENT_TAB_RESTORES and restore_hidden_tabs are respected. +// Selected tabs are always restored regardless of this pref. +pref("browser.sessionstore.restore_on_demand", false); // Whether to automatically restore hidden tabs (i.e., tabs in other tab groups) or not pref("browser.sessionstore.restore_hidden_tabs", false); @@ -881,7 +881,7 @@ pref("browser.privatebrowsing.dont_prompt_on_enter", false); pref("browser.bookmarks.editDialog.firstEditField", "namePicker"); // base url for the wifi geolocation network provider -pref("geo.wifi.uri", "https://www.google.com/loc/json"); +pref("geo.wifi.uri", "https://maps.googleapis.com/maps/api/browserlocation/json"); pref("geo.wifi.protocol", 0); // Whether to use a panel that looks like an OS X sheet for customization @@ -1054,7 +1054,7 @@ pref("devtools.editor.expandtab", true); // provides programmer-specific editor features such as syntax highlighting, // indenting and bracket recognition. It may not be appropriate for all // locales (esp. RTL) or a11y situations. -pref("devtools.editor.component", "textarea"); +pref("devtools.editor.component", "orion"); // Whether the character encoding menu is under the main Firefox button. This // preference is a string so that localizers can alter it. diff --git a/browser/base/content/domplate.jsm b/browser/base/content/domplate.jsm index 1493d9ec585c..1f6e5b67cf0c 100644 --- a/browser/base/content/domplate.jsm +++ b/browser/base/content/domplate.jsm @@ -1631,7 +1631,7 @@ BaseTemplates.AttrTag = " ", domplate.SPAN({"class": "nodeName editable"}, "$attr.nodeName"), "="", - domplate.SPAN({"class": "nodeValue editable"}, "$attr.nodeValue"), + domplate.SPAN({"class": "nodeValue editable", "data-attributeName": "$attr.nodeName"}, "$attr.nodeValue"), """); BaseTemplates.TextTag = diff --git a/browser/base/content/inspector.html b/browser/base/content/inspector.html index f37a7f610b1b..3322ca53614b 100644 --- a/browser/base/content/inspector.html +++ b/browser/base/content/inspector.html @@ -7,5 +7,8 @@ +
+ +
diff --git a/browser/base/content/inspector.js b/browser/base/content/inspector.js index c1790a80455c..3f60e13924bd 100644 --- a/browser/base/content/inspector.js +++ b/browser/base/content/inspector.js @@ -26,6 +26,7 @@ * Mihai Șucan * Julian Viereck * Paul Rouget + * Kyle Simpson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -70,6 +71,11 @@ const INSPECTOR_NOTIFICATIONS = { // Fires once the Inspector is closed. CLOSED: "inspector-closed", + + // Event notifications for the attribute-value editor + EDITOR_OPENED: "inspector-editor-opened", + EDITOR_CLOSED: "inspector-editor-closed", + EDITOR_SAVED: "inspector-editor-saved", }; /////////////////////////////////////////////////////////////////////////// @@ -591,6 +597,8 @@ var InspectorUI = { this.ioBox = new InsideOutBox(this, this.treePanelDiv); this.ioBox.createObjectBox(this.win.document.documentElement); this.treeLoaded = true; + this.editingContext = null; + this.editingEvents = {}; // initialize the highlighter this.initializeHighlighter(); @@ -614,6 +622,7 @@ var InspectorUI = { this.treeIFrame.setAttribute("flex", "1"); this.treeIFrame.setAttribute("type", "content"); this.treeIFrame.setAttribute("onclick", "InspectorUI.onTreeClick(event)"); + this.treeIFrame.setAttribute("ondblclick", "InspectorUI.onTreeDblClick(event);"); this.treeIFrame = this.treePanel.insertBefore(this.treeIFrame, resizerBox); } @@ -817,6 +826,11 @@ var InspectorUI = { */ closeInspectorUI: function IUI_closeInspectorUI(aKeepStore) { + // if currently editing an attribute value, closing the + // highlighter/HTML panel dismisses the editor + if (this.editingContext) + this.closeEditor(); + if (this.closing || !this.win || !this.browser) { return; } @@ -893,6 +907,11 @@ var InspectorUI = { */ startInspecting: function IUI_startInspecting() { + // if currently editing an attribute value, starting + // "live inspection" mode closes the editor + if (this.editingContext) + this.closeEditor(); + document.getElementById("inspector-inspect-toolbutton").checked = true; this.attachPageListeners(); this.inspecting = true; @@ -933,6 +952,11 @@ var InspectorUI = { */ select: function IUI_select(aNode, forceUpdate, aScroll) { + // if currently editing an attribute value, using the + // highlighter dismisses the editor + if (this.editingContext) + this.closeEditor(); + if (!aNode) aNode = this.defaultSelection; @@ -1044,6 +1068,17 @@ var InspectorUI = { */ onTreeClick: function IUI_onTreeClick(aEvent) { + // if currently editing an attribute value, clicking outside + // the editor dismisses the editor + if (this.editingContext) { + this.closeEditor(); + + // clicking outside the editor ONLY closes the editor + // so, cancel the rest of the processing of this event + aEvent.preventDefault(); + return; + } + let node; let target = aEvent.target; let hitTwisty = false; @@ -1068,6 +1103,220 @@ var InspectorUI = { } }, + /** + * Handle double-click events in the html tree panel. + * (double-clicking an attribute value allows it to be edited) + * @param aEvent + * The mouse event. + */ + onTreeDblClick: function IUI_onTreeDblClick(aEvent) + { + // if already editing an attribute value, double-clicking elsewhere + // in the tree is the same as a click, which dismisses the editor + if (this.editingContext) + this.closeEditor(); + + let target = aEvent.target; + + if (this.hasClass(target, "nodeValue")) { + let repObj = this.getRepObject(target); + let attrName = target.getAttribute("data-attributeName"); + let attrVal = target.innerHTML; + + this.editAttributeValue(target, repObj, attrName, attrVal); + } + }, + + /** + * Starts the editor for an attribute value. + * @param aAttrObj + * The DOM object representing the attribute value in the HTML Tree + * @param aRepObj + * The original DOM (target) object being inspected/edited + * @param aAttrName + * The name of the attribute being edited + * @param aAttrVal + * The current value of the attribute being edited + */ + editAttributeValue: + function IUI_editAttributeValue(aAttrObj, aRepObj, aAttrName, aAttrVal) + { + let editor = this.treeBrowserDocument.getElementById("attribute-editor"); + let editorInput = + this.treeBrowserDocument.getElementById("attribute-editor-input"); + let attrDims = aAttrObj.getBoundingClientRect(); + // figure out actual viewable viewport dimensions (sans scrollbars) + let viewportWidth = this.treeBrowserDocument.documentElement.clientWidth; + let viewportHeight = this.treeBrowserDocument.documentElement.clientHeight; + + // saves the editing context for use when the editor is saved/closed + this.editingContext = { + attrObj: aAttrObj, + repObj: aRepObj, + attrName: aAttrName + }; + + // highlight attribute-value node in tree while editing + this.addClass(aAttrObj, "editingAttributeValue"); + + // show the editor + this.addClass(editor, "editing"); + + // offset the editor below the attribute-value node being edited + let editorVeritcalOffset = 2; + + // keep the editor comfortably within the bounds of the viewport + let editorViewportBoundary = 5; + + // outer editor is sized based on the box inside it + editorInput.style.width = Math.min(attrDims.width, viewportWidth - + editorViewportBoundary) + "px"; + editorInput.style.height = Math.min(attrDims.height, viewportHeight - + editorViewportBoundary) + "px"; + let editorDims = editor.getBoundingClientRect(); + + // calculate position for the editor according to the attribute node + let editorLeft = attrDims.left + this.treeIFrame.contentWindow.scrollX - + // center the editor against the attribute value + ((editorDims.width - attrDims.width) / 2); + let editorTop = attrDims.top + this.treeIFrame.contentWindow.scrollY + + attrDims.height + editorVeritcalOffset; + + // but, make sure the editor stays within the visible viewport + editorLeft = Math.max(0, Math.min( + (this.treeIFrame.contentWindow.scrollX + + viewportWidth - editorDims.width), + editorLeft) + ); + editorTop = Math.max(0, Math.min( + (this.treeIFrame.contentWindow.scrollY + + viewportHeight - editorDims.height), + editorTop) + ); + + // position the editor + editor.style.left = editorLeft + "px"; + editor.style.top = editorTop + "px"; + + // set and select the text + editorInput.value = aAttrVal; + editorInput.select(); + + // listen for editor specific events + this.bindEditorEvent(editor, "click", function(aEvent) { + aEvent.stopPropagation(); + }); + this.bindEditorEvent(editor, "dblclick", function(aEvent) { + aEvent.stopPropagation(); + }); + this.bindEditorEvent(editor, "keypress", + this.handleEditorKeypress.bind(this)); + + // event notification + Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, + null); + }, + + /** + * Handle binding an event handler for the editor. + * (saves the callback for easier unbinding later) + * @param aEditor + * The DOM object for the editor + * @param aEventName + * The name of the event to listen for + * @param aEventCallback + * The callback to bind to the event (and also to save for later + * unbinding) + */ + bindEditorEvent: + function IUI_bindEditorEvent(aEditor, aEventName, aEventCallback) + { + this.editingEvents[aEventName] = aEventCallback; + aEditor.addEventListener(aEventName, aEventCallback, false); + }, + + /** + * Handle unbinding an event handler from the editor. + * (unbinds the previously bound and saved callback) + * @param aEditor + * The DOM object for the editor + * @param aEventName + * The name of the event being listened for + */ + unbindEditorEvent: function IUI_unbindEditorEvent(aEditor, aEventName) + { + aEditor.removeEventListener(aEventName, this.editingEvents[aEventName], + false); + this.editingEvents[aEventName] = null; + }, + + /** + * Handle keypress events in the editor. + * @param aEvent + * The keyboard event. + */ + handleEditorKeypress: function IUI_handleEditorKeypress(aEvent) + { + if (aEvent.which == KeyEvent.DOM_VK_RETURN) { + this.saveEditor(); + } else if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) { + this.closeEditor(); + } + }, + + /** + * Close the editor and cleanup. + */ + closeEditor: function IUI_closeEditor() + { + let editor = this.treeBrowserDocument.getElementById("attribute-editor"); + let editorInput = + this.treeBrowserDocument.getElementById("attribute-editor-input"); + + // remove highlight from attribute-value node in tree + this.removeClass(this.editingContext.attrObj, "editingAttributeValue"); + + // hide editor + this.removeClass(editor, "editing"); + + // stop listening for editor specific events + this.unbindEditorEvent(editor, "click"); + this.unbindEditorEvent(editor, "dblclick"); + this.unbindEditorEvent(editor, "keypress"); + + // clean up after the editor + editorInput.value = ""; + editorInput.blur(); + this.editingContext = null; + this.editingEvents = {}; + + // event notification + Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, + null); + }, + + /** + * Commit the edits made in the editor, then close it. + */ + saveEditor: function IUI_saveEditor() + { + let editorInput = + this.treeBrowserDocument.getElementById("attribute-editor-input"); + + // set the new attribute value on the original target DOM element + this.editingContext.repObj.setAttribute(this.editingContext.attrName, + editorInput.value); + + // update the HTML tree attribute value + this.editingContext.attrObj.innerHTML = editorInput.value; + + // event notification + Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, + null); + + this.closeEditor(); + }, + /** * Attach event listeners to content window and child windows to enable * highlighting and click to stop inspection. diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 627d80154227..b4f9aacc043c 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -79,7 +79,8 @@ nsContextMenu.prototype = { this.hasPageMenu = false; if (!aIsShift) { - this.hasPageMenu = PageMenu.init(this.target, aXulMenu); + this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(this.target, + aXulMenu); } this.isFrameImage = document.getElementById("isFrameImage"); diff --git a/browser/base/content/tabview/groupitems.js b/browser/base/content/tabview/groupitems.js index f5c331b1b864..8b0578d8120d 100644 --- a/browser/base/content/tabview/groupitems.js +++ b/browser/base/content/tabview/groupitems.js @@ -515,7 +515,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), { // make some room for the expand button if we're stacked let isStacked = (options && options.forceStacked) || this.isStacked(); if (isStacked) - box.height -= 33; // 33px room for the expand button + box.height -= this.$expander.height() + 9; // the button height plus padding return box; }, @@ -1237,7 +1237,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), { showExpandControl: function GroupItem_showExpandControl() { let parentBB = this.getBounds(); let childBB = this.getChild(0).getBounds(); - let padding = 7; this.$expander .show() .css({ @@ -1363,15 +1362,17 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), { let shouldStack = this.shouldStack(childrenToArrange.length + (options.addTab ? 1 : 0)); let shouldStackArrange = (shouldStack && !this.expanded); - let box = this.getContentBounds({forceStacked: shouldStackArrange}); - + let box; + // if we should stack and we're not expanded if (shouldStackArrange) { this.showExpandControl(); + box = this.getContentBounds({forceStacked: true}); this._stackArrange(childrenToArrange, box, options); return false; } else { this.hideExpandControl(); + box = this.getContentBounds({forceStacked: false}); // a dropIndex is returned return this._gridArrange(childrenToArrange, box, options); } diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 4cc801b13d3f..e643dab3c974 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -177,6 +177,7 @@ _BROWSER_FILES = \ browser_bug647886.js \ browser_bug655584.js \ browser_bug664672.js \ + browser_canonizeURL.js \ browser_findbarClose.js \ browser_keywordBookmarklets.js \ browser_contextSearchTabPosition.js \ diff --git a/browser/base/content/test/browser_canonizeURL.js b/browser/base/content/test/browser_canonizeURL.js new file mode 100644 index 000000000000..b544416f96fa --- /dev/null +++ b/browser/base/content/test/browser_canonizeURL.js @@ -0,0 +1,54 @@ +function test() { + waitForExplicitFinish(); + testNext(); +} + +var pairs = [ + ["example", "http://www.example.net/"], + ["ex-ample", "http://www.ex-ample.net/"], + [" example ", "http://www.example.net/"], + [" example/foo ", "http://www.example.net/foo"], + [" example/foo bar ", "http://www.example.net/foo%20bar"], + ["example.net", "http://example.net/"], + ["http://example", "http://example/"], + ["example:8080", "http://example:8080/"], + ["ex-ample.foo", "http://ex-ample.foo/"], + ["example.foo/bar ", "http://example.foo/bar"], + ["1.1.1.1", "http://1.1.1.1/"], + ["ftp://example", "ftp://example/"], + ["ftp.example.bar", "ftp://ftp.example.bar/"], + ["ex ample", Services.search.originalDefaultEngine.getSubmission("ex ample").uri.spec], +]; + +function testNext() { + if (!pairs.length) { + finish(); + return; + } + + let [inputValue, expectedURL] = pairs.shift(); + + gBrowser.addProgressListener({ + onStateChange: function onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) { + if (aStateFlags & Ci.nsIWebProgressListener.STATE_START && + aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) { + is(aRequest.originalURI.spec, expectedURL, + "entering '" + inputValue + "' loads expected URL"); + + gBrowser.removeProgressListener(this); + gBrowser.stop(); + + executeSoon(testNext); + } + } + }); + + gURLBar.addEventListener("focus", function onFocus() { + gURLBar.removeEventListener("focus", onFocus); + EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true }); + }); + + gBrowser.selectedBrowser.focus(); + gURLBar.inputField.value = inputValue; + gURLBar.focus(); +} diff --git a/browser/base/content/test/inspector/Makefile.in b/browser/base/content/test/inspector/Makefile.in index 2d7537c6b012..1fb25b8436f6 100644 --- a/browser/base/content/test/inspector/Makefile.in +++ b/browser/base/content/test/inspector/Makefile.in @@ -56,6 +56,7 @@ _BROWSER_FILES = \ browser_inspector_treePanel_result.html \ browser_inspector_registertools.js \ browser_inspector_bug_665880.js \ + browser_inspector_editor.js \ $(NULL) libs:: $(_BROWSER_FILES) diff --git a/browser/base/content/test/inspector/browser_inspector_editor.js b/browser/base/content/test/inspector/browser_inspector_editor.js new file mode 100644 index 000000000000..ca2378f80c4e --- /dev/null +++ b/browser/base/content/test/inspector/browser_inspector_editor.js @@ -0,0 +1,233 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* ***** BEGIN LICENSE BLOCK ***** +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + * + * Contributor(s): + * Rob Campbell + * Mihai Sucan + * Kyle Simpson + * + * ***** END LICENSE BLOCK ***** */ + +let doc; +let div; +let editorTestSteps; + +function doNextStep() { + editorTestSteps.next(); +} + +function setupEditorTests() +{ + div = doc.createElement("div"); + div.setAttribute("id", "foobar"); + div.setAttribute("class", "barbaz"); + doc.body.appendChild(div); + + Services.obs.addObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false); + InspectorUI.toggleInspectorUI(); +} + +function runEditorTests() +{ + Services.obs.removeObserver(runEditorTests, INSPECTOR_NOTIFICATIONS.OPENED, false); + InspectorUI.stopInspecting(); + + // setup generator for async test steps + editorTestSteps = doEditorTestSteps(); + + // add step listeners + Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false); + Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false); + Services.obs.addObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false); + + // start the tests + doNextStep(); +} + +function doEditorTestSteps() +{ + let editor = InspectorUI.treeBrowserDocument.getElementById("attribute-editor"); + let editorInput = InspectorUI.treeBrowserDocument.getElementById("attribute-editor-input"); + + // Step 1: grab and test the attribute-value nodes in the HTML panel, then open editor + let attrValNode_id = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='id']")[0]; + let attrValNode_class = InspectorUI.treeBrowserDocument.querySelectorAll(".nodeValue.editable[data-attributeName='class']")[0]; + + is(attrValNode_id.innerHTML, "foobar", "Step 1: we have the correct `id` attribute-value node in the HTML panel"); + is(attrValNode_class.innerHTML, "barbaz", "we have the correct `class` attribute-value node in the HTML panel"); + + // double-click the `id` attribute-value node to open the editor + executeSoon(function() { + // firing 2 clicks right in a row to simulate a double-click + EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView); + }); + + yield; // End of Step 1 + + + // Step 2: validate editing session, enter new attribute value into editor, and save input + ok(InspectorUI.editingContext, "Step 2: editor session started"); + + let editorVisible = editor.classList.contains("editing"); + ok(editorVisible, "editor popup visible"); + + // check if the editor popup is "near" the correct position + let editorDims = editor.getBoundingClientRect(); + let attrValNodeDims = attrValNode_id.getBoundingClientRect(); + let editorPositionOK = (editorDims.left >= (attrValNodeDims.left - editorDims.width - 5)) && + (editorDims.right <= (attrValNodeDims.right + editorDims.width + 5)) && + (editorDims.top >= (attrValNodeDims.top - editorDims.height - 5)) && + (editorDims.bottom <= (attrValNodeDims.bottom + editorDims.height + 5)); + + ok(editorPositionOK, "editor position acceptable"); + + // check to make sure the attribute-value node being edited is properly highlighted + let attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue"); + ok(attrValNodeHighlighted, "`id` attribute-value node is editor-highlighted"); + + is(InspectorUI.editingContext.repObj, div, "editor session has correct reference to div"); + is(InspectorUI.editingContext.attrObj, attrValNode_id, "editor session has correct reference to `id` attribute-value node in HTML panel"); + is(InspectorUI.editingContext.attrName, "id", "editor session knows correct attribute-name"); + + editorInput.value = "Hello World"; + editorInput.focus(); + + // hit to save the inputted value + executeSoon(function() { + EventUtils.synthesizeKey("VK_RETURN", {}, attrValNode_id.ownerDocument.defaultView); + }); + + // two `yield` statements, to trap both the "SAVED" and "CLOSED" events that will be triggered + yield; + yield; // End of Step 2 + + + // Step 3: validate that the previous editing session saved correctly, then open editor on `class` attribute value + ok(!InspectorUI.editingContext, "Step 3: editor session ended"); + editorVisible = editor.classList.contains("editing"); + ok(!editorVisible, "editor popup hidden"); + attrValNodeHighlighted = attrValNode_id.classList.contains("editingAttributeValue"); + ok(!attrValNodeHighlighted, "`id` attribute-value node is no longer editor-highlighted"); + is(div.getAttribute("id"), "Hello World", "`id` attribute-value successfully updated"); + is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel successfully updated"); + + // double-click the `class` attribute-value node to open the editor + executeSoon(function() { + // firing 2 clicks right in a row to simulate a double-click + EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {clickCount: 2}, attrValNode_class.ownerDocument.defaultView); + }); + + yield; // End of Step 3 + + + // Step 4: enter value into editor, then hit to discard it + ok(InspectorUI.editingContext, "Step 4: editor session started"); + editorVisible = editor.classList.contains("editing"); + ok(editorVisible, "editor popup visible"); + + is(InspectorUI.editingContext.attrObj, attrValNode_class, "editor session has correct reference to `class` attribute-value node in HTML panel"); + is(InspectorUI.editingContext.attrName, "class", "editor session knows correct attribute-name"); + + editorInput.value = "Hello World"; + editorInput.focus(); + + // hit to discard the inputted value + executeSoon(function() { + EventUtils.synthesizeKey("VK_ESCAPE", {}, attrValNode_class.ownerDocument.defaultView); + }); + + yield; // End of Step 4 + + + // Step 5: validate that the previous editing session discarded correctly, then open editor on `id` attribute value again + ok(!InspectorUI.editingContext, "Step 5: editor session ended"); + editorVisible = editor.classList.contains("editing"); + ok(!editorVisible, "editor popup hidden"); + is(div.getAttribute("class"), "barbaz", "`class` attribute-value *not* updated"); + is(attrValNode_class.innerHTML, "barbaz", "attribute-value node in HTML panel *not* updated"); + + // double-click the `id` attribute-value node to open the editor + executeSoon(function() { + // firing 2 clicks right in a row to simulate a double-click + EventUtils.synthesizeMouse(attrValNode_id, 2, 2, {clickCount: 2}, attrValNode_id.ownerDocument.defaultView); + }); + + yield; // End of Step 5 + + + // Step 6: validate that editor opened again, then test double-click inside of editor (should do nothing) + ok(InspectorUI.editingContext, "Step 6: editor session started"); + editorVisible = editor.classList.contains("editing"); + ok(editorVisible, "editor popup visible"); + + // double-click on the editor input box + executeSoon(function() { + // firing 2 clicks right in a row to simulate a double-click + EventUtils.synthesizeMouse(editorInput, 2, 2, {clickCount: 2}, editorInput.ownerDocument.defaultView); + + // since the previous double-click is supposed to do nothing, + // wait a brief moment, then move on to the next step + executeSoon(function() { + doNextStep(); + }); + }); + + yield; // End of Step 6 + + + // Step 7: validate that editing session is still correct, then enter a value and try a click + // outside of editor (should cancel the editing session) + ok(InspectorUI.editingContext, "Step 7: editor session still going"); + editorVisible = editor.classList.contains("editing"); + ok(editorVisible, "editor popup still visible"); + + editorInput.value = "all your base are belong to us"; + + // single-click the `class` attribute-value node + executeSoon(function() { + EventUtils.synthesizeMouse(attrValNode_class, 2, 2, {}, attrValNode_class.ownerDocument.defaultView); + }); + + yield; // End of Step 7 + + + // Step 8: validate that the editor was closed and that the editing was not saved + ok(!InspectorUI.editingContext, "Step 8: editor session ended"); + editorVisible = editor.classList.contains("editing"); + ok(!editorVisible, "editor popup hidden"); + is(div.getAttribute("id"), "Hello World", "`id` attribute-value *not* updated"); + is(attrValNode_id.innerHTML, "Hello World", "attribute-value node in HTML panel *not* updated"); + + // End of Step 8 + + // end of all steps, so clean up + Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_OPENED, false); + Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_CLOSED, false); + Services.obs.removeObserver(doNextStep, INSPECTOR_NOTIFICATIONS.EDITOR_SAVED, false); + + executeSoon(finishUp); +} + +function finishUp() { + doc = div = null; + InspectorUI.closeInspectorUI(); + gBrowser.removeCurrentTab(); + finish(); +} + +function test() +{ + waitForExplicitFinish(); + gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function() { + gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + doc = content.document; + waitForFocus(setupEditorTests, content); + }, true); + + content.location = "data:text/html,basic tests for html panel attribute-value editor"; +} + diff --git a/browser/base/content/test/inspector/browser_inspector_treePanel_result.html b/browser/base/content/test/inspector/browser_inspector_treePanel_result.html index 1156a1f251ed..9dcaf41e71ef 100644 --- a/browser/base/content/test/inspector/browser_inspector_treePanel_result.html +++ b/browser/base/content/test/inspector/browser_inspector_treePanel_result.html @@ -1,8 +1,8 @@ - \ No newline at end of file diff --git a/browser/base/content/test/tabview/browser_tabview_bug595601.js b/browser/base/content/test/tabview/browser_tabview_bug595601.js index 7784d28f662c..a6feccd8df4f 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug595601.js +++ b/browser/base/content/test/tabview/browser_tabview_bug595601.js @@ -35,14 +35,11 @@ function test() { registerCleanupFunction(function () { TabsProgressListener.uninit(); - Services.prefs.clearUserPref("browser.sessionstore.max_concurrent_tabs"); Services.prefs.clearUserPref("browser.sessionstore.restore_hidden_tabs"); ss.setBrowserState(stateBackup); }); - Services.prefs.setIntPref("browser.sessionstore.max_concurrent_tabs", 3); - TabView._initFrame(function () { executeSoon(testRestoreWithHiddenTabs); }); diff --git a/browser/base/content/test/test_contextmenu.html b/browser/base/content/test/test_contextmenu.html index cc43f1f0a021..b7b3e6586a42 100644 --- a/browser/base/content/test/test_contextmenu.html +++ b/browser/base/content/test/test_contextmenu.html @@ -49,9 +49,10 @@ function executeCopyCommand(command, expectedValue) is(input.value, expectedValue, "paste for command " + command); } -function invokeItemAction(ident) +function invokeItemAction(generatedItemId) { - var item = contextMenu.getElementsByAttribute("ident", ident)[0]; + var item = contextMenu.getElementsByAttribute("generateditemid", + generatedItemId)[0]; ok(item, "Got generated XUL menu item"); item.doCommand(); is(pagemenu.hasAttribute("hopeless"), false, "attribute got removed"); @@ -69,7 +70,7 @@ function getVisibleMenuItems(aMenu, aData) { if (key) key = key.toLowerCase(); - var isGenerated = item.hasAttribute("generated"); + var isGenerated = item.hasAttribute("generateditemid"); if (item.nodeName == "menuitem") { var isSpellSuggestion = item.className == "spell-suggestion"; diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 2278e5f7b5c6..641e750a43b5 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -367,7 +367,7 @@ // Only add the suffix when the URL bar value isn't already "URL-like", // and only if we get a keyboard event, to match user expectations. - if (!/^\s*(www|https?)\b|\/\s*$/i.test(url) && + if (/^\s*[^.:\/\s]+(?:\/.*|\s*)$/i.test(url) && (aTriggeringEvent instanceof KeyEvent)) { #ifdef XP_MACOSX let accel = aTriggeringEvent.metaKey; @@ -402,24 +402,15 @@ // Tack www. and suffix on. If user has appended directories, insert // suffix before them (bug 279035). Be careful not to get two slashes. - // Also, don't add the suffix if it's in the original url (bug 233853). let firstSlash = url.indexOf("/"); - let existingSuffix = url.indexOf(suffix.substring(0, suffix.length - 1)); - - // * Logic for slash and existing suffix (example) - // No slash, no suffix: Add suffix (mozilla) - // No slash, yes suffix: Add slash (mozilla.com) - // Yes slash, no suffix: Insert suffix (mozilla/stuff) - // Yes slash, suffix before slash: Do nothing (mozilla.com/stuff) - // Yes slash, suffix after slash: Insert suffix (mozilla/?stuff=.com) if (firstSlash >= 0) { - if (existingSuffix == -1 || existingSuffix > firstSlash) - url = url.substring(0, firstSlash) + suffix + - url.substring(firstSlash + 1); - } else - url = url + (existingSuffix == -1 ? suffix : "/"); + url = url.substring(0, firstSlash) + suffix + + url.substring(firstSlash + 1); + } else { + url = url + suffix; + } url = "http://www." + url; } diff --git a/browser/components/build/nsModule.cpp b/browser/components/build/nsModule.cpp index 4a557e612a8c..5dd5efc68d1f 100644 --- a/browser/components/build/nsModule.cpp +++ b/browser/components/build/nsModule.cpp @@ -53,7 +53,6 @@ #if !defined(XP_OS2) #include "nsOperaProfileMigrator.h" #endif -#include "nsSeamonkeyProfileMigrator.h" #if defined(XP_WIN) && !defined(__MINGW32__) #include "nsIEProfileMigrator.h" #elif defined(XP_MACOSX) @@ -85,7 +84,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsOperaProfileMigrator) #endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsProfileMigrator) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSeamonkeyProfileMigrator) #if defined(XP_WIN) && !defined(__MINGW32__) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator) #elif defined(XP_MACOSX) @@ -114,7 +112,6 @@ NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID); #if !defined(XP_OS2) NS_DEFINE_NAMED_CID(NS_OPERAPROFILEMIGRATOR_CID); #endif -NS_DEFINE_NAMED_CID(NS_SEAMONKEYPROFILEMIGRATOR_CID); NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID); static const mozilla::Module::CIDEntry kBrowserCIDs[] = { @@ -136,7 +133,6 @@ static const mozilla::Module::CIDEntry kBrowserCIDs[] = { #if !defined(XP_OS2) { &kNS_OPERAPROFILEMIGRATOR_CID, false, NULL, nsOperaProfileMigratorConstructor }, #endif - { &kNS_SEAMONKEYPROFILEMIGRATOR_CID, false, NULL, nsSeamonkeyProfileMigratorConstructor }, { &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor }, { NULL } }; @@ -173,7 +169,6 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = { #if !defined(XP_OS2) { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "opera", &kNS_OPERAPROFILEMIGRATOR_CID }, #endif - { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey", &kNS_SEAMONKEYPROFILEMIGRATOR_CID }, { NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID }, { NULL } }; diff --git a/browser/components/migration/content/migration.js b/browser/components/migration/content/migration.js index 34688b7c81ca..30f86d0fe9ad 100644 --- a/browser/components/migration/content/migration.js +++ b/browser/components/migration/content/migration.js @@ -340,9 +340,6 @@ var MigrationWizard = { case "safari": source = "sourceNameSafari"; break; - case "seamonkey": - source = "sourceNameSeamonkey"; - break; } // semi-wallpaper for crash when multiple profiles exist, since we haven't initialized mSourceProfile in places diff --git a/browser/components/migration/content/migration.xul b/browser/components/migration/content/migration.xul index 7ec730cc0028..91b0fdc3bbfb 100644 --- a/browser/components/migration/content/migration.xul +++ b/browser/components/migration/content/migration.xul @@ -70,19 +70,14 @@ browser/components/migration/src/nsProfileMigrator.cpp --> #ifdef XP_MACOSX - #elifdef XP_UNIX - #elifdef XP_WIN #ifndef NO_IE_MIGRATOR #endif - -#else - #endif