diff --git a/browser/app/permissions b/browser/app/permissions index 9c421e8510e0..bc3cddbbf436 100644 --- a/browser/app/permissions +++ b/browser/app/permissions @@ -8,6 +8,7 @@ # UITour host uitour 1 www.mozilla.org +host uitour 1 self-repair.mozilla.org host uitour 1 support.mozilla.org host uitour 1 about:home diff --git a/browser/base/content/abouthome/aboutHome.js b/browser/base/content/abouthome/aboutHome.js index 74e452245779..4ebfe977f434 100644 --- a/browser/base/content/abouthome/aboutHome.js +++ b/browser/base/content/abouthome/aboutHome.js @@ -307,10 +307,11 @@ function onSearchSubmit(aEvent) if (engineName && searchTerms.length > 0) { // Send an event that will perform a search and Firefox Health Report will // record that a search from about:home has occurred. - + let useNewTab = aEvent && aEvent.button == 1; let eventData = { engineName: engineName, - searchTerms: searchTerms + searchTerms: searchTerms, + useNewTab: useNewTab, }; if (searchText.hasAttribute("selection-index")) { diff --git a/browser/base/content/content.js b/browser/base/content/content.js index 107694f7cd00..d1e490fc4fac 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -1064,3 +1064,38 @@ addMessageListener("ContextMenu:SaveVideoFrameAsImage", (message) => { dataURL: canvas.toDataURL("image/jpeg", ""), }); }); + +addMessageListener("ContextMenu:MediaCommand", (message) => { + let media = message.objects.element; + + switch (message.data.command) { + case "play": + media.play(); + break; + case "pause": + media.pause(); + break; + case "mute": + media.muted = true; + break; + case "unmute": + media.muted = false; + break; + case "playbackRate": + media.playbackRate = message.data.data; + break; + case "hidecontrols": + media.removeAttribute("controls"); + break; + case "showcontrols": + media.setAttribute("controls", "true"); + break; + case "hidestats": + case "showstats": + let event = media.ownerDocument.createEvent("CustomEvent"); + event.initCustomEvent("media-showStatistics", false, true, + message.data.command == "showstats"); + media.dispatchEvent(event); + break; + } +}); diff --git a/browser/base/content/newtab/search.js b/browser/base/content/newtab/search.js index b868aef2c0db..63d769108fb6 100644 --- a/browser/base/content/newtab/search.js +++ b/browser/base/content/newtab/search.js @@ -49,11 +49,12 @@ let gSearch = { let searchText = this._nodes.text; let searchStr = searchText.value; if (this.currentEngineName && searchStr.length) { - + let useNewTab = event && event.button == 1; let eventData = { engineName: this.currentEngineName, searchString: searchStr, whence: "newtab", + useNewTab: useNewTab, } if (searchText.hasAttribute("selection-index")) { @@ -244,7 +245,7 @@ let gSearch = { let parent = document.getElementById("newtab-scrollbox"); this._suggestionController = new SearchSuggestionUIController(this._nodes.text, parent, - () => this.search()); + event => this.search(event)); } this._suggestionController.engineName = engine.name; }, diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 84465d5ad8d5..abb368990785 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -1668,37 +1668,10 @@ nsContextMenu.prototype = { }, mediaCommand : function CM_mediaCommand(command, data) { - var media = this.target; - - switch (command) { - case "play": - media.play(); - break; - case "pause": - media.pause(); - break; - case "mute": - media.muted = true; - break; - case "unmute": - media.muted = false; - break; - case "playbackRate": - media.playbackRate = data; - break; - case "hidecontrols": - media.removeAttribute("controls"); - break; - case "showcontrols": - media.setAttribute("controls", "true"); - break; - case "hidestats": - case "showstats": - var event = media.ownerDocument.createEvent("CustomEvent"); - event.initCustomEvent("media-showStatistics", false, true, command == "showstats"); - media.dispatchEvent(event); - break; - } + let mm = this.browser.messageManager; + mm.sendAsyncMessage("ContextMenu:MediaCommand", + {command: command, data: data}, + {element: this.target}); }, copyMediaLocation : function () { diff --git a/browser/base/content/searchSuggestionUI.js b/browser/base/content/searchSuggestionUI.js index ba49b23102b4..2690536d8c2c 100644 --- a/browser/base/content/searchSuggestionUI.js +++ b/browser/base/content/searchSuggestionUI.js @@ -32,7 +32,8 @@ const HTML_NS = "http://www.w3.org/1999/xhtml"; * @param onClick * A function that's called when a search suggestion is clicked. Ideally * we could call submit() on inputElement's ancestor form, but that - * doesn't trigger submit listeners. + * doesn't trigger submit listeners. The function is passed one argument, + * the click event. * @param idPrefix * The IDs of elements created by the object will be prefixed with this * string. @@ -234,6 +235,9 @@ SearchSuggestionUIController.prototype = { }, _onMousedown: function (event) { + if (event.button == 2) { + return; + } let idx = this._indexOfTableRowOrDescendent(event.target); let suggestion = this.suggestionAtIndex(idx); this._stickyInputValue = suggestion; @@ -251,7 +255,7 @@ SearchSuggestionUIController.prototype = { this.input.setAttribute("selection-kind", "mouse"); this._hideSuggestions(); if (this.onClick) { - this.onClick.call(null); + this.onClick.call(null, event); } }, diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index e42352b479d9..4176e92c6155 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -984,7 +984,7 @@ - + class="search-panel-header search-panel-current-input"> @@ -1011,11 +1010,9 @@ + class="search-panel-one-offs"/> diff --git a/browser/components/customizableui/CustomizableWidgets.jsm b/browser/components/customizableui/CustomizableWidgets.jsm index d8d908205dce..11a18df29ab4 100644 --- a/browser/components/customizableui/CustomizableWidgets.jsm +++ b/browser/components/customizableui/CustomizableWidgets.jsm @@ -10,6 +10,8 @@ this.EXPORTED_SYMBOLS = ["CustomizableWidgets"]; Cu.import("resource:///modules/CustomizableUI.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry", + "resource:///modules/BrowserUITelemetry.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils", @@ -1012,6 +1014,7 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) { this._ensureSanitizer(); this._sanitizer.range = this._getSanitizeRange(doc); let group = doc.getElementById("PanelUI-panic-timeSpan"); + BrowserUITelemetry.countPanicEvent(group.selectedItem.id); group.selectedItem = doc.getElementById("PanelUI-panic-5min"); let itemsToClear = [ "cookies", "history", "openWindows", "formdata", "sessions", "cache", "downloads" diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index 243ccb41e43f..0d3c8c340966 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -730,6 +730,11 @@ let MozLoopServiceInternal = { let string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); gLocalizedStrings.set(string.key, string.value); } + // Supply the strings from the branding bundle on a per-need basis. + let brandBundle = + Services.strings.createBundle("chrome://branding/locale/brand.properties"); + // Unfortunately the `brandShortName` string is used by Loop with a lowercase 'N'. + gLocalizedStrings.set("brandShortname", brandBundle.GetStringFromName("brandShortName")); return gLocalizedStrings; }, diff --git a/browser/components/loop/content/shared/js/actions.js b/browser/components/loop/content/shared/js/actions.js index 7ff1951d7f7b..59529ac83d65 100644 --- a/browser/components/loop/content/shared/js/actions.js +++ b/browser/components/loop/content/shared/js/actions.js @@ -202,6 +202,8 @@ loop.shared.actions = (function() { * Used to start a screen share. */ StartScreenShare: Action.define("startScreenShare", { + // The part of the screen to share, e.g. "window" or "browser". + type: String }), /** diff --git a/browser/components/loop/content/shared/js/otSdkDriver.js b/browser/components/loop/content/shared/js/otSdkDriver.js index 4ee8c59068e0..d5e688036558 100644 --- a/browser/components/loop/content/shared/js/otSdkDriver.js +++ b/browser/components/loop/content/shared/js/otSdkDriver.js @@ -89,14 +89,13 @@ loop.OTSdkDriver = (function() { /** * Initiates a screen sharing publisher. */ - startScreenShare: function() { + startScreenShare: function(actionData) { this.dispatcher.dispatch(new sharedActions.ScreenSharingState({ state: SCREEN_SHARE_STATES.PENDING })); var config = this._getCopyPublisherConfig(); - // This is temporary until we get a sharing type selector - config.videoSource = "window"; + config.videoSource = actionData.type; this.screenshare = this.sdk.initPublisher(this.getScreenShareElementFunc(), config); diff --git a/browser/components/loop/content/shared/js/utils.js b/browser/components/loop/content/shared/js/utils.js index 67e1cf880148..95a2dca53541 100644 --- a/browser/components/loop/content/shared/js/utils.js +++ b/browser/components/loop/content/shared/js/utils.js @@ -143,14 +143,16 @@ loop.shared.utils = (function(mozL10n) { return; } navigator.mozLoop.composeEmail( - mozL10n.get("share_email_subject4", { - clientShortname: mozL10n.get("clientShortname2") + mozL10n.get("share_email_subject5", { + clientShortname2: mozL10n.get("clientShortname2") }), - mozL10n.get("share_email_body4", { + mozL10n.get("share_email_body5", { callUrl: callUrl, - clientShortname: mozL10n.get("clientShortname2"), + brandShortname: mozL10n.get("brandShortname"), + clientShortname2: mozL10n.get("clientShortname2"), + clientSuperShortname: mozL10n.get("clientSuperShortname"), learnMoreUrl: navigator.mozLoop.getLoopPref("learnMoreUrl") - }), + }).replace(/\r\n/g, "\n").replace(/\n/g, "\r\n"), recipient ); } diff --git a/browser/components/loop/content/shared/js/views.js b/browser/components/loop/content/shared/js/views.js index e7d3f1203b64..5eb4658d089d 100644 --- a/browser/components/loop/content/shared/js/views.js +++ b/browser/components/loop/content/shared/js/views.js @@ -102,8 +102,18 @@ loop.shared.views = (function(_, l10n) { } }, + _startScreenShare: function(type) { + this.props.dispatcher.dispatch(new sharedActions.StartScreenShare({ + type: type + })); + }, + + _handleShareTabs: function() { + this._startScreenShare("browser"); + }, + _handleShareWindows: function() { - this.props.dispatcher.dispatch(new sharedActions.StartScreenShare({})); + this._startScreenShare("window"); }, _getTitle: function() { @@ -143,6 +153,9 @@ loop.shared.views = (function(_, l10n) { isActive ? null : React.createElement("span", {className: "chevron"}) ), React.createElement("ul", {ref: "menu", className: dropdownMenuClasses}, + React.createElement("li", {onClick: this._handleShareTabs, className: "disabled"}, + l10n.get("share_tabs_button_title") + ), React.createElement("li", {onClick: this._handleShareWindows}, l10n.get("share_windows_button_title") ) diff --git a/browser/components/loop/content/shared/js/views.jsx b/browser/components/loop/content/shared/js/views.jsx index 7bc9b3e419a7..e193f4792bf2 100644 --- a/browser/components/loop/content/shared/js/views.jsx +++ b/browser/components/loop/content/shared/js/views.jsx @@ -102,8 +102,18 @@ loop.shared.views = (function(_, l10n) { } }, + _startScreenShare: function(type) { + this.props.dispatcher.dispatch(new sharedActions.StartScreenShare({ + type: type + })); + }, + + _handleShareTabs: function() { + this._startScreenShare("browser"); + }, + _handleShareWindows: function() { - this.props.dispatcher.dispatch(new sharedActions.StartScreenShare({})); + this._startScreenShare("window"); }, _getTitle: function() { @@ -143,6 +153,9 @@ loop.shared.views = (function(_, l10n) { {isActive ? null : }
    +
  • + {l10n.get("share_tabs_button_title")} +
  • {l10n.get("share_windows_button_title")}
  • diff --git a/browser/components/loop/test/shared/otSdkDriver_test.js b/browser/components/loop/test/shared/otSdkDriver_test.js index 60e636eaccf2..1750e8cf49b8 100644 --- a/browser/components/loop/test/shared/otSdkDriver_test.js +++ b/browser/components/loop/test/shared/otSdkDriver_test.js @@ -139,7 +139,9 @@ describe("loop.OTSdkDriver", function () { }); it("should dispatch a `ScreenSharingState` action", function() { - driver.startScreenShare(new sharedActions.StartScreenShare()); + driver.startScreenShare(new sharedActions.StartScreenShare({ + type: "window" + })); sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, @@ -149,7 +151,9 @@ describe("loop.OTSdkDriver", function () { }); it("should initialize a publisher", function() { - driver.startScreenShare(new sharedActions.StartScreenShare()); + driver.startScreenShare(new sharedActions.StartScreenShare({ + type: "window" + })); sinon.assert.calledOnce(sdk.initPublisher); sinon.assert.calledWithMatch(sdk.initPublisher, @@ -161,7 +165,9 @@ describe("loop.OTSdkDriver", function () { beforeEach(function() { driver.getScreenShareElementFunc = function() {}; - driver.startScreenShare(new sharedActions.StartScreenShare()); + driver.startScreenShare(new sharedActions.StartScreenShare({ + type: "window" + })); sandbox.stub(dispatcher, "dispatch"); @@ -611,7 +617,9 @@ describe("loop.OTSdkDriver", function () { driver.getScreenShareElementFunc = function() {}; - driver.startScreenShare(new sharedActions.StartScreenShare()); + driver.startScreenShare(new sharedActions.StartScreenShare({ + type: "window" + })); sandbox.stub(dispatcher, "dispatch"); }); diff --git a/browser/components/loop/test/shared/utils_test.js b/browser/components/loop/test/shared/utils_test.js index 0567150736d1..8b98835b77b2 100644 --- a/browser/components/loop/test/shared/utils_test.js +++ b/browser/components/loop/test/shared/utils_test.js @@ -152,8 +152,8 @@ describe("loop.shared.utils", function() { // fake mozL10n sandbox.stub(navigator.mozL10n, "get", function(id) { switch(id) { - case "share_email_subject4": return "subject"; - case "share_email_body4": return "body"; + case "share_email_subject5": return "subject"; + case "share_email_body5": return "body"; } }); composeEmail = sandbox.spy(); diff --git a/browser/components/loop/test/shared/views_test.js b/browser/components/loop/test/shared/views_test.js index 0537a8b8e93a..31b4364ce6c5 100644 --- a/browser/components/loop/test/shared/views_test.js +++ b/browser/components/loop/test/shared/views_test.js @@ -152,7 +152,7 @@ describe("loop.shared.views", function() { expect(comp.state.showMenu).eql(true); }); - it("should dispatch a StartScreenShare action on option click in screenshare dropdown", + it("should dispatch a 'browser' StartScreenShare action on option click", function() { var comp = TestUtils.renderIntoDocument( React.createElement(sharedViews.ScreenShareControlButton, { @@ -166,7 +166,24 @@ describe("loop.shared.views", function() { sinon.assert.calledOnce(dispatcher.dispatch); sinon.assert.calledWithExactly(dispatcher.dispatch, - new sharedActions.StartScreenShare({})); + new sharedActions.StartScreenShare({ type: "browser" })); + }); + + it("should dispatch a 'window' StartScreenShare action on option click", + function() { + var comp = TestUtils.renderIntoDocument( + React.createElement(sharedViews.ScreenShareControlButton, { + dispatcher: dispatcher, + visible: true, + state: SCREEN_SHARE_STATES.INACTIVE + })); + + TestUtils.Simulate.click(comp.getDOMNode().querySelector( + ".conversation-window-dropdown > li:last-child")); + + sinon.assert.calledOnce(dispatcher.dispatch); + sinon.assert.calledWithExactly(dispatcher.dispatch, + new sharedActions.StartScreenShare({ type: "window" })); }); it("should dispatch a EndScreenShare action on click when the state is active", diff --git a/browser/components/places/tests/browser/browser.ini b/browser/components/places/tests/browser/browser.ini index d0903d9a4709..b1aabcc128ae 100644 --- a/browser/components/places/tests/browser/browser.ini +++ b/browser/components/places/tests/browser/browser.ini @@ -29,9 +29,6 @@ skip-if = e10s && (os == 'linux' || os == 'mac') # Bug 1116457 skip-if = e10s [browser_forgetthissite_single.js] -# disabled for very frequent oranges - bug 551540 -skip-if = true - [browser_library_commands.js] [browser_drag_bookmarks_on_toolbar.js] skip-if = e10s # Bug ?????? - test fails - "Number of dragged items should be the same. - Got 0, expected 1" diff --git a/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js b/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js index 8a99db778541..a7089b49700e 100644 --- a/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js +++ b/browser/components/places/tests/browser/browser_0_library_left_pane_migration.js @@ -4,6 +4,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/. */ +"use strict"; + /** * Test we correctly migrate Library left pane to the latest version. * Note: this test MUST be the first between browser chrome tests, or results @@ -12,39 +14,7 @@ const TEST_URI = "http://www.mozilla.org/"; -function onLibraryReady(organizer) { - // Check left pane. - ok(PlacesUIUtils.leftPaneFolderId > 0, - "Left pane folder correctly created"); - var leftPaneItems = - PlacesUtils.annotations - .getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO); - is(leftPaneItems.length, 1, - "We correctly have only 1 left pane folder"); - var leftPaneRoot = leftPaneItems[0]; - is(leftPaneRoot, PlacesUIUtils.leftPaneFolderId, - "leftPaneFolderId getter has correct value"); - // Check version has been upgraded. - var version = - PlacesUtils.annotations.getItemAnnotation(leftPaneRoot, - PlacesUIUtils.ORGANIZER_FOLDER_ANNO); - is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, - "Left pane version has been correctly upgraded"); - - // Check left pane is populated. - organizer.PlacesOrganizer.selectLeftPaneQuery('History'); - is(organizer.PlacesOrganizer._places.selectedNode.itemId, - PlacesUIUtils.leftPaneQueries["History"], - "Library left pane is populated and working"); - - // Close Library window. - organizer.close(); - // No need to cleanup anything, we have a correct left pane now. - finish(); -} - -function test() { - waitForExplicitFinish(); +add_task(function* () { // Sanity checks. ok(PlacesUtils, "PlacesUtils is running in chrome context"); ok(PlacesUIUtils, "PlacesUIUtils is running in chrome context"); @@ -52,42 +22,69 @@ function test() { "Left pane version in chrome context, current version is: " + PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION ); // Check if we have any left pane folder already set, remove it eventually. - var leftPaneItems = PlacesUtils.annotations + let leftPaneItems = PlacesUtils.annotations .getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO); if (leftPaneItems.length > 0) { // The left pane has already been created, touching it now would cause // next tests to rely on wrong values (and possibly crash) is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder"); // Check version. - var version = PlacesUtils.annotations.getItemAnnotation(leftPaneItems[0], + let version = PlacesUtils.annotations.getItemAnnotation(leftPaneItems[0], PlacesUIUtils.ORGANIZER_FOLDER_ANNO); is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, "Left pane version is actual"); ok(true, "left pane has already been created, skipping test"); - finish(); return; } // Create a fake left pane folder with an old version (current version - 1). - var fakeLeftPaneRoot = - PlacesUtils.bookmarks.createFolder(PlacesUtils.placesRootId, "", - PlacesUtils.bookmarks.DEFAULT_INDEX); - PlacesUtils.annotations.setItemAnnotation(fakeLeftPaneRoot, + let folder = yield PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.rootGuid, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, + type: PlacesUtils.bookmarks.TYPE_FOLDER, + title: "" + }); + + let folderId = yield PlacesUtils.promiseItemId(folder.guid); + PlacesUtils.annotations.setItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION - 1, 0, PlacesUtils.annotations.EXPIRE_NEVER); // Check fake left pane root has been correctly created. - var leftPaneItems = + leftPaneItems = PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO); is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder"); - is(leftPaneItems[0], fakeLeftPaneRoot, "left pane root itemId is correct"); + is(leftPaneItems[0], folderId, "left pane root itemId is correct"); // Check version. - var version = PlacesUtils.annotations.getItemAnnotation(fakeLeftPaneRoot, + let version = PlacesUtils.annotations.getItemAnnotation(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO); is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION - 1, "Left pane version correctly set"); // Open Library, this will upgrade our left pane version. - openLibrary(onLibraryReady); -} + let organizer = yield promiseLibrary(); + + // Check left pane. + ok(PlacesUIUtils.leftPaneFolderId > 0, "Left pane folder correctly created"); + leftPaneItems = + PlacesUtils.annotations.getItemsWithAnnotation(PlacesUIUtils.ORGANIZER_FOLDER_ANNO); + is(leftPaneItems.length, 1, "We correctly have only 1 left pane folder"); + let leftPaneRoot = leftPaneItems[0]; + is(leftPaneRoot, PlacesUIUtils.leftPaneFolderId, + "leftPaneFolderId getter has correct value"); + + // Check version has been upgraded. + version = PlacesUtils.annotations.getItemAnnotation(leftPaneRoot, + PlacesUIUtils.ORGANIZER_FOLDER_ANNO); + is(version, PlacesUIUtils.ORGANIZER_LEFTPANE_VERSION, + "Left pane version has been correctly upgraded"); + + // Check left pane is populated. + organizer.PlacesOrganizer.selectLeftPaneQuery("History"); + is(organizer.PlacesOrganizer._places.selectedNode.itemId, + PlacesUIUtils.leftPaneQueries["History"], + "Library left pane is populated and working"); + + yield promiseLibraryClosed(organizer); +}); diff --git a/browser/components/places/tests/browser/browser_410196_paste_into_tags.js b/browser/components/places/tests/browser/browser_410196_paste_into_tags.js index ed5984250c2c..2acb1d9b763d 100644 --- a/browser/components/places/tests/browser/browser_410196_paste_into_tags.js +++ b/browser/components/places/tests/browser/browser_410196_paste_into_tags.js @@ -2,139 +2,113 @@ * http://creativecommons.org/publicdomain/zero/1.0/ */ -function add_bookmark(aURI) { - return PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId, - aURI, PlacesUtils.bookmarks.DEFAULT_INDEX, - "bookmark/" + aURI.spec); -} +"use strict"; -Components.utils.import("resource://gre/modules/NetUtil.jsm"); +const TEST_URL = Services.io.newURI("http://example.com/", null, null); +const MOZURISPEC = Services.io.newURI("http://mozilla.com/", null, null); -const TEST_URL = "http://example.com/"; -const MOZURISPEC = "http://mozilla.com/"; +add_task(function* () { + let organizer = yield promiseLibrary(); -let gLibrary; -let PlacesOrganizer; -let ContentTree; - -function test() { - waitForExplicitFinish(); - gLibrary = openLibrary(onLibraryReady); -} - -function onLibraryReady() { ok(PlacesUtils, "PlacesUtils in scope"); ok(PlacesUIUtils, "PlacesUIUtils in scope"); - PlacesOrganizer = gLibrary.PlacesOrganizer; + let PlacesOrganizer = organizer.PlacesOrganizer; ok(PlacesOrganizer, "Places organizer in scope"); - ContentTree = gLibrary.ContentTree; + let ContentTree = organizer.ContentTree; ok(ContentTree, "ContentTree is in scope"); - tests.makeHistVisit(function() { - tests.makeTag(); - tests.focusTag(); - waitForClipboard(function(aData) !!aData, - tests.copyHistNode, - onClipboardReady, - PlacesUtils.TYPE_X_MOZ_PLACE); + let visits = {uri: MOZURISPEC, transition: PlacesUtils.history.TRANSITION_TYPED}; + yield PlacesTestUtils.addVisits(visits); + + // create an initial tag to work with + let bm = yield PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.unfiledGuid, + index: PlacesUtils.bookmarks.DEFAULT_INDEX, + type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + title: "bookmark/" + TEST_URL.spec, + url: TEST_URL }); -} -function onClipboardReady() { - tests.focusTag(); + ok(bm, "A bookmark was added"); + PlacesUtils.tagging.tagURI(TEST_URL, ["foo"]); + let tags = PlacesUtils.tagging.getTagsForURI(TEST_URL); + is(tags[0], "foo", "tag is foo"); + + // focus the new tag + focusTag(PlacesOrganizer); + + let populate = () => copyHistNode(PlacesOrganizer, ContentTree); + yield promiseClipboard(populate, PlacesUtils.TYPE_X_MOZ_PLACE); + + focusTag(PlacesOrganizer); PlacesOrganizer._places.controller.paste(); - tests.historyNode(); - tests.checkForBookmarkInUI(); - gLibrary.close(); + // re-focus the history again + PlacesOrganizer.selectLeftPaneQuery("History"); + let histContainer = PlacesOrganizer._places.selectedNode; + PlacesUtils.asContainer(histContainer); + histContainer.containerOpen = true; + PlacesOrganizer._places.selectNode(histContainer.getChild(0)); + let histNode = ContentTree.view.view.nodeForTreeIndex(0); + ok(histNode, "histNode exists: " + histNode.title); + + // check to see if the history node is tagged! + tags = PlacesUtils.tagging.getTagsForURI(MOZURISPEC); + ok(tags.length == 1, "history node is tagged: " + tags.length); + + // check if a bookmark was created + let bookmarks = []; + yield PlacesUtils.bookmarks.fetch({url: MOZURISPEC}, bm => { + bookmarks.push(bm); + }); + ok(bookmarks.length > 0, "bookmark exists for the tagged history item"); + + // is the bookmark visible in the UI? + // get the Unsorted Bookmarks node + PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks"); + + // now we can see what is in the ContentTree tree + let unsortedNode = ContentTree.view.view.nodeForTreeIndex(1); + ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri); + is(unsortedNode.uri, MOZURISPEC.spec, "node uri's are the same"); + + yield promiseLibraryClosed(organizer); // Remove new Places data we created. - PlacesUtils.tagging.untagURI(NetUtil.newURI(MOZURISPEC), ["foo"]); - PlacesUtils.tagging.untagURI(NetUtil.newURI(TEST_URL), ["foo"]); - let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(TEST_URL)); + PlacesUtils.tagging.untagURI(MOZURISPEC, ["foo"]); + PlacesUtils.tagging.untagURI(TEST_URL, ["foo"]); + tags = PlacesUtils.tagging.getTagsForURI(TEST_URL); is(tags.length, 0, "tags are gone"); - PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); - PlacesTestUtils.clearHistory().then(finish); + yield PlacesUtils.bookmarks.eraseEverything(); + yield PlacesTestUtils.clearHistory(); +}); + +function focusTag(PlacesOrganizer) { + PlacesOrganizer.selectLeftPaneQuery("Tags"); + let tags = PlacesOrganizer._places.selectedNode; + tags.containerOpen = true; + let fooTag = tags.getChild(0); + let tagNode = fooTag; + PlacesOrganizer._places.selectNode(fooTag); + is(tagNode.title, 'foo', "tagNode title is foo"); + let ip = PlacesOrganizer._places.insertionPoint; + ok(ip.isTag, "IP is a tag"); } -let tests = { - - makeHistVisit: function(aCallback) { - // need to add a history object - let testURI1 = NetUtil.newURI(MOZURISPEC); - isnot(testURI1, null, "testURI is not null"); - PlacesTestUtils.addVisits( - {uri: testURI1, transition: PlacesUtils.history.TRANSITION_TYPED} - ).then(aCallback); - }, - - makeTag: function() { - // create an initial tag to work with - let bmId = add_bookmark(NetUtil.newURI(TEST_URL)); - ok(bmId > 0, "A bookmark was added"); - PlacesUtils.tagging.tagURI(NetUtil.newURI(TEST_URL), ["foo"]); - let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(TEST_URL)); - is(tags[0], 'foo', "tag is foo"); - }, - - focusTag: function (){ - // focus the new tag - PlacesOrganizer.selectLeftPaneQuery("Tags"); - let tags = PlacesOrganizer._places.selectedNode; - tags.containerOpen = true; - let fooTag = tags.getChild(0); - let tagNode = fooTag; - PlacesOrganizer._places.selectNode(fooTag); - is(tagNode.title, 'foo', "tagNode title is foo"); - let ip = PlacesOrganizer._places.insertionPoint; - ok(ip.isTag, "IP is a tag"); - }, - - copyHistNode: function (){ - // focus the history object - PlacesOrganizer.selectLeftPaneQuery("History"); - let histContainer = PlacesOrganizer._places.selectedNode; - PlacesUtils.asContainer(histContainer); - histContainer.containerOpen = true; - PlacesOrganizer._places.selectNode(histContainer.getChild(0)); - let histNode = ContentTree.view.view.nodeForTreeIndex(0); - ContentTree.view.selectNode(histNode); - is(histNode.uri, MOZURISPEC, - "historyNode exists: " + histNode.uri); - // copy the history node - ContentTree.view.controller.copy(); - }, - - historyNode: function (){ - // re-focus the history again - PlacesOrganizer.selectLeftPaneQuery("History"); - let histContainer = PlacesOrganizer._places.selectedNode; - PlacesUtils.asContainer(histContainer); - histContainer.containerOpen = true; - PlacesOrganizer._places.selectNode(histContainer.getChild(0)); - let histNode = ContentTree.view.view.nodeForTreeIndex(0); - ok(histNode, "histNode exists: " + histNode.title); - // check to see if the history node is tagged! - let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(MOZURISPEC)); - ok(tags.length == 1, "history node is tagged: " + tags.length); - // check if a bookmark was created - let isBookmarked = PlacesUtils.bookmarks.isBookmarked(NetUtil.newURI(MOZURISPEC)); - is(isBookmarked, true, MOZURISPEC + " is bookmarked"); - let bookmarkIds = PlacesUtils.bookmarks.getBookmarkIdsForURI( - NetUtil.newURI(histNode.uri)); - ok(bookmarkIds.length > 0, "bookmark exists for the tagged history item: " + bookmarkIds); - }, - - checkForBookmarkInUI: function(){ - // is the bookmark visible in the UI? - // get the Unsorted Bookmarks node - PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks"); - // now we can see what is in the ContentTree tree - let unsortedNode = ContentTree.view.view.nodeForTreeIndex(1); - ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri); - is(unsortedNode.uri, MOZURISPEC, "node uri's are the same"); - }, -}; +function copyHistNode(PlacesOrganizer, ContentTree) { + // focus the history object + PlacesOrganizer.selectLeftPaneQuery("History"); + let histContainer = PlacesOrganizer._places.selectedNode; + PlacesUtils.asContainer(histContainer); + histContainer.containerOpen = true; + PlacesOrganizer._places.selectNode(histContainer.getChild(0)); + let histNode = ContentTree.view.view.nodeForTreeIndex(0); + ContentTree.view.selectNode(histNode); + is(histNode.uri, MOZURISPEC.spec, + "historyNode exists: " + histNode.uri); + // copy the history node + ContentTree.view.controller.copy(); +} diff --git a/browser/components/places/tests/browser/browser_416459_cut.js b/browser/components/places/tests/browser/browser_416459_cut.js index ec78df1b797c..d59a2722cadd 100644 --- a/browser/components/places/tests/browser/browser_416459_cut.js +++ b/browser/components/places/tests/browser/browser_416459_cut.js @@ -1,22 +1,14 @@ /* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; const TEST_URL = "http://example.com/"; -let gLibrary; -let gItemId; -let PlacesOrganizer; -let ContentTree; - -function test() { - waitForExplicitFinish(); - gLibrary = openLibrary(onLibraryReady); -} - -function onLibraryReady() { - PlacesOrganizer = gLibrary.PlacesOrganizer; - ContentTree = gLibrary.ContentTree; +add_task(function* () { + let organizer = yield promiseLibrary(); + let PlacesOrganizer = organizer.PlacesOrganizer; + let ContentTree = organizer.ContentTree; // Sanity checks. ok(PlacesUtils, "PlacesUtils in scope"); @@ -24,49 +16,44 @@ function onLibraryReady() { ok(PlacesOrganizer, "PlacesOrganizer in scope"); ok(ContentTree, "ContentTree is in scope"); - gItemId = PlacesUtils.bookmarks.insertBookmark( - PlacesUtils.toolbarFolderId, NetUtil.newURI(TEST_URL), - PlacesUtils.bookmarks.DEFAULT_INDEX, "test" - ); + let bm = yield PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + url: TEST_URL + }); - selectBookmarkIn("BookmarksToolbar"); + yield selectBookmarkIn(organizer, bm, "BookmarksToolbar"); - waitForClipboard(function(aData) !!aData, - cutSelection, - onClipboardReady, - PlacesUtils.TYPE_X_MOZ_PLACE); -} + yield promiseClipboard(() => { + info("Cutting selection"); + ContentTree.view.controller.cut(); + }, PlacesUtils.TYPE_X_MOZ_PLACE); + + info("Selecting UnfiledBookmarks in the left pane"); + PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks"); + info("Pasting clipboard"); + ContentTree.view.controller.paste(); + + yield selectBookmarkIn(organizer, bm, "UnfiledBookmarks"); + + yield promiseLibraryClosed(organizer); + yield PlacesUtils.bookmarks.eraseEverything(); +}); + +let selectBookmarkIn = Task.async(function* (organizer, bm, aLeftPaneQuery) { + let PlacesOrganizer = organizer.PlacesOrganizer; + let ContentTree = organizer.ContentTree; -function selectBookmarkIn(aLeftPaneQuery) { info("Selecting " + aLeftPaneQuery + " in the left pane"); PlacesOrganizer.selectLeftPaneQuery(aLeftPaneQuery); let rootId = PlacesUtils.getConcreteItemId(PlacesOrganizer._places.selectedNode); - is(PlacesUtils.bookmarks.getFolderIdForItem(gItemId), rootId, + + bm = yield PlacesUtils.bookmarks.fetch(bm.guid); + is((yield PlacesUtils.promiseItemId(bm.parentGuid)), rootId, "Bookmark has the right parent"); + info("Selecting the bookmark in the right pane"); - ContentTree.view.selectItems([gItemId]); + ContentTree.view.selectItems([yield PlacesUtils.promiseItemId(bm.guid)]); let bookmarkNode = ContentTree.view.selectedNode; is(bookmarkNode.uri, TEST_URL, "Found the expected bookmark"); -} - -function cutSelection() { - info("Cutting selection"); - ContentTree.view.controller.cut(); -} - -function pasteClipboard(aLeftPaneQuery) { - info("Selecting " + aLeftPaneQuery + " in the left pane"); - PlacesOrganizer.selectLeftPaneQuery(aLeftPaneQuery); - info("Pasting clipboard"); - ContentTree.view.controller.paste(); -} - -function onClipboardReady() { - pasteClipboard("UnfiledBookmarks"); - selectBookmarkIn("UnfiledBookmarks"); - - // Cleanup. - gLibrary.close(); - PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId); - finish(); -} +}); diff --git a/browser/components/places/tests/browser/browser_425884.js b/browser/components/places/tests/browser/browser_425884.js index 4140ac023451..bca377b420b4 100644 --- a/browser/components/places/tests/browser/browser_425884.js +++ b/browser/components/places/tests/browser/browser_425884.js @@ -1,54 +1,66 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* 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/. */ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ -function test() { +"use strict"; + +/* + Deep copy of bookmark data, using the front-end codepath: + + - create test folder A + - add a subfolder to folder A, and add items to it + - validate folder A (sanity check) + - copy folder A, creating new folder B, using the front-end path + - validate folder B + - undo copy transaction + - validate folder B (empty) + - redo copy transaction + - validate folder B's contents +*/ + +add_task(function* () { // sanity check ok(PlacesUtils, "checking PlacesUtils, running in chrome context?"); ok(PlacesUIUtils, "checking PlacesUIUtils, running in chrome context?"); - /* - Deep copy of bookmark data, using the front-end codepath: + let toolbarId = PlacesUtils.toolbarFolderId; + let toolbarNode = PlacesUtils.getFolderContents(toolbarId).root; - - create test folder A - - add a subfolder to folder A, and add items to it - - validate folder A (sanity check) - - copy folder A, creating new folder B, using the front-end path - - validate folder B - - undo copy transaction - - validate folder B (empty) - - redo copy transaction - - validate folder B's contents - - */ - - var toolbarId = PlacesUtils.toolbarFolderId; - var toolbarNode = PlacesUtils.getFolderContents(toolbarId).root; - - var oldCount = toolbarNode.childCount; - var testRootId = PlacesUtils.bookmarks.createFolder(toolbarId, "test root", -1); + let oldCount = toolbarNode.childCount; + let testRoot = yield PlacesUtils.bookmarks.insert({ + parentGuid: PlacesUtils.bookmarks.toolbarGuid, + type: PlacesUtils.bookmarks.TYPE_FOLDER, + title: "test root" + }); is(toolbarNode.childCount, oldCount+1, "confirm test root node is a container, and is empty"); - var testRootNode = toolbarNode.getChild(toolbarNode.childCount-1); + + let testRootNode = toolbarNode.getChild(toolbarNode.childCount-1); testRootNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); testRootNode.containerOpen = true; is(testRootNode.childCount, 0, "confirm test root node is a container, and is empty"); // create folder A, fill it, validate its contents - var folderAId = PlacesUtils.bookmarks.createFolder(testRootId, "A", -1); - populate(folderAId); - var folderANode = PlacesUtils.getFolderContents(folderAId).root; + let folderA = yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_FOLDER, + parentGuid: testRoot.guid, + title: "A" + }); + + yield populate(folderA); + + let folderAId = yield PlacesUtils.promiseItemId(folderA.guid); + let folderANode = PlacesUtils.getFolderContents(folderAId).root; validate(folderANode); is(testRootNode.childCount, 1, "create test folder"); // copy it, using the front-end helper functions - var serializedNode = PlacesUtils.wrapNode(folderANode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER); - var rawNode = PlacesUtils.unwrapNodes(serializedNode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER).shift(); + let serializedNode = PlacesUtils.wrapNode(folderANode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER); + let rawNode = PlacesUtils.unwrapNodes(serializedNode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER).shift(); // confirm serialization ok(rawNode.type, "confirm json node"); folderANode.containerOpen = false; - var transaction = PlacesUIUtils.makeTransaction(rawNode, + let testRootId = yield PlacesUtils.promiseItemId(testRoot.guid); + let transaction = PlacesUIUtils.makeTransaction(rawNode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER, testRootId, -1, @@ -59,7 +71,7 @@ function test() { is(testRootNode.childCount, 2, "create test folder via copy"); // validate the copy - var folderBNode = testRootNode.getChild(1); + let folderBNode = testRootNode.getChild(1); validate(folderBNode); // undo the transaction, confirm the removal @@ -78,14 +90,28 @@ function test() { // clean up PlacesUtils.transactionManager.undoTransaction(); - PlacesUtils.bookmarks.removeItem(folderAId); -} + yield PlacesUtils.bookmarks.remove(folderA.guid); +}); -function populate(aFolderId) { - var folderId = PlacesUtils.bookmarks.createFolder(aFolderId, "test folder", -1); - PlacesUtils.bookmarks.insertBookmark(folderId, PlacesUtils._uri("http://foo"), -1, "test bookmark"); - PlacesUtils.bookmarks.insertSeparator(folderId, -1); -} +let populate = Task.async(function* (parentFolder) { + let folder = yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_FOLDER, + parentGuid: parentFolder.guid, + title: "test folder" + }); + + yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_BOOKMARK, + parentGuid: folder.guid, + title: "test bookmark", + url: "http://foo" + }); + + yield PlacesUtils.bookmarks.insert({ + type: PlacesUtils.bookmarks.TYPE_SEPARATOR, + parentGuid: folder.guid + }); +}); function validate(aNode) { PlacesUtils.asContainer(aNode); diff --git a/browser/components/places/tests/browser/browser_forgetthissite_single.js b/browser/components/places/tests/browser/browser_forgetthissite_single.js index ef207ed19d51..3211129b7e94 100644 --- a/browser/components/places/tests/browser/browser_forgetthissite_single.js +++ b/browser/components/places/tests/browser/browser_forgetthissite_single.js @@ -2,69 +2,77 @@ * 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 TEST_URIs = [ + "http://www.mozilla.org/test1", + "http://www.mozilla.org/test2" +]; + // This test makes sure that the Forget This Site command is hidden for multiple // selections. -function test() { - // initialization - waitForExplicitFinish(); - +add_task(function* () { // Add a history entry. - let TEST_URIs = ["http://www.mozilla.org/test1", "http://www.mozilla.org/test2"]; ok(PlacesUtils, "checking PlacesUtils, running in chrome context?"); - let places = []; - TEST_URIs.forEach(function(TEST_URI) { - places.push({uri: PlacesUtils._uri(TEST_URI), - transition: PlacesUtils.history.TRANSITION_TYPED}); - }); - PlacesTestUtils.addVisits(places).then(() => { - testForgetThisSiteVisibility(1, function() { - testForgetThisSiteVisibility(2, function() { - // Cleanup - PlacesTestUtils.clearHistory().then(finish); - }); - }); - }); - function testForgetThisSiteVisibility(selectionCount, funcNext) { - openLibrary(function (organizer) { - // Select History in the left pane. - organizer.PlacesOrganizer.selectLeftPaneQuery('History'); - let PO = organizer.PlacesOrganizer; - let histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); - histContainer.containerOpen = true; - PO._places.selectNode(histContainer.getChild(0)); - // Select the first history entry. - let doc = organizer.document; - let tree = PO._content; - let selection = tree.view.selection; - selection.clearSelection(); - selection.rangedSelect(0, selectionCount - 1, true); - is(selection.count, selectionCount, - "The selected range is as big as expected"); - // Open the context menu - let contextmenu = doc.getElementById("placesContext"); - contextmenu.addEventListener("popupshown", function() { - contextmenu.removeEventListener("popupshown", arguments.callee, true); - let forgetThisSite = doc.getElementById("placesContext_deleteHost"); - let hideForgetThisSite = (selectionCount != 1); - is(forgetThisSite.hidden, hideForgetThisSite, - "The Forget this site menu item should " + (hideForgetThisSite ? "" : "not ") + - "be hidden with " + selectionCount + " items selected"); - // Close the context menu - contextmenu.hidePopup(); - // Wait for the Organizer window to actually be closed - organizer.addEventListener("unload", function () { - organizer.removeEventListener("unload", arguments.callee, false); - // Proceed - funcNext(); - }, false); - // Close Library window. - organizer.close(); - }, true); - // Get cell coordinates - var rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text"); - // Initiate a context menu for the selected cell - EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {type: "contextmenu"}, organizer); - }); - } + let places = []; + let transition = PlacesUtils.history.TRANSITION_TYPED; + TEST_URIs.forEach(uri => places.push({uri: PlacesUtils._uri(uri), transition})); + + yield PlacesTestUtils.addVisits(places); + yield testForgetThisSiteVisibility(1); + yield testForgetThisSiteVisibility(2); + + // Cleanup. + yield PlacesTestUtils.clearHistory(); +}); + +let testForgetThisSiteVisibility = Task.async(function* (selectionCount) { + let organizer = yield promiseLibrary(); + + // Select History in the left pane. + organizer.PlacesOrganizer.selectLeftPaneQuery("History"); + let PO = organizer.PlacesOrganizer; + let histContainer = PO._places.selectedNode.QueryInterface(Ci.nsINavHistoryContainerResultNode); + histContainer.containerOpen = true; + PO._places.selectNode(histContainer.getChild(0)); + + // Select the first history entry. + let doc = organizer.document; + let tree = doc.getElementById("placeContent"); + let selection = tree.view.selection; + selection.clearSelection(); + selection.rangedSelect(0, selectionCount - 1, true); + is(selection.count, selectionCount, "The selected range is as big as expected"); + + // Open the context menu. + let contextmenu = doc.getElementById("placesContext"); + let popupShown = promisePopupShown(contextmenu); + + // Get cell coordinates. + let rect = tree.treeBoxObject.getCoordsForCellItem(0, tree.columns[0], "text"); + // Initiate a context menu for the selected cell. + EventUtils.synthesizeMouse(tree.body, rect.x + rect.width / 2, rect.y + rect.height / 2, {type: "contextmenu", button: 2}, organizer); + yield popupShown; + + let forgetThisSite = doc.getElementById("placesContext_deleteHost"); + let hideForgetThisSite = (selectionCount != 1); + is(forgetThisSite.hidden, hideForgetThisSite, + `The Forget this site menu item should ${hideForgetThisSite ? "" : "not "}` + + ` be hidden with ${selectionCount} items selected`); + + // Close the context menu. + contextmenu.hidePopup(); + + // Close the library window. + yield promiseLibraryClosed(organizer); +}); + +function promisePopupShown(popup) { + return new Promise(resolve => { + popup.addEventListener("popupshown", function onShown() { + popup.removeEventListener("popupshown", onShown, true); + resolve(); + }, true); + }); } diff --git a/browser/components/places/tests/browser/head.js b/browser/components/places/tests/browser/head.js index 4d4f18fa7873..734db44acfad 100644 --- a/browser/components/places/tests/browser/head.js +++ b/browser/components/places/tests/browser/head.js @@ -43,17 +43,31 @@ function openLibrary(callback, aLeftPaneRoot) { * Hierarchy to open and select in the left pane. */ function promiseLibrary(aLeftPaneRoot) { - let deferred = Promise.defer(); - let library = Services.wm.getMostRecentWindow("Places:Organizer"); - if (library && !library.closed) { - if (aLeftPaneRoot) - library.PlacesOrganizer.selectLeftPaneContainerByHierarchy(aLeftPaneRoot); - deferred.resolve(library); - } - else { - openLibrary(aLibrary => deferred.resolve(aLibrary), aLeftPaneRoot); - } - return deferred.promise; + return new Promise(resolve => { + let library = Services.wm.getMostRecentWindow("Places:Organizer"); + if (library && !library.closed) { + if (aLeftPaneRoot) { + library.PlacesOrganizer.selectLeftPaneContainerByHierarchy(aLeftPaneRoot); + } + resolve(library); + } + else { + openLibrary(resolve, aLeftPaneRoot); + } + }); +} + +function promiseLibraryClosed(organizer) { + return new Promise(resolve => { + // Wait for the Organizer window to actually be closed + organizer.addEventListener("unload", function onUnload() { + organizer.removeEventListener("unload", onUnload); + resolve(); + }); + + // Close Library window. + organizer.close(); + }); } /** @@ -67,12 +81,9 @@ function promiseLibrary(aLeftPaneRoot) { * Data flavor to expect. */ function promiseClipboard(aPopulateClipboardFn, aFlavor) { - let deferred = Promise.defer(); - waitForClipboard(function (aData) !!aData, - aPopulateClipboardFn, - function () { deferred.resolve(); }, - aFlavor); - return deferred.promise; + return new Promise(resolve => { + waitForClipboard(data => !!data, aPopulateClipboardFn, resolve, aFlavor); + }); } /** diff --git a/browser/components/preferences/fonts.js b/browser/components/preferences/fonts.js index 299ba1567b4f..84100e20416f 100644 --- a/browser/components/preferences/fonts.js +++ b/browser/components/preferences/fonts.js @@ -108,6 +108,37 @@ var gFontsDialog = { { var useDocumentFonts = document.getElementById("useDocumentFonts"); return useDocumentFonts.checked ? 1 : 0; - } + }, + + onBeforeAccept: function () + { + // Only care in in-content prefs + if (!window.frameElement) { + return true; + } + + let preferences = document.querySelectorAll("preference[id*='font.minimum-size']"); + // It would be good if we could avoid touching languages the pref pages won't use, but + // unfortunately the language group APIs (deducing language groups from language codes) + // are C++ - only. So we just check all the things the user touched: + // Don't care about anything up to 24px, or if this value is the same as set previously: + preferences = Array.filter(preferences, prefEl => { + return prefEl.value > 24 && prefEl.value != prefEl.valueFromPreferences; + }); + if (!preferences.length) { + return; + } + + let strings = document.getElementById("bundlePreferences"); + let title = strings.getString("veryLargeMinimumFontTitle"); + let confirmLabel = strings.getString("acceptVeryLargeMinimumFont"); + let warningMessage = strings.getString("veryLargeMinimumFontWarning"); + let {Services} = Components.utils.import("resource://gre/modules/Services.jsm", {}); + let flags = Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL | + Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING | + Services.prompt.BUTTON_POS_1_DEFAULT; + let buttonChosen = Services.prompt.confirmEx(window, title, warningMessage, flags, confirmLabel, null, "", "", {}); + return buttonChosen == 0; + }, }; diff --git a/browser/components/preferences/fonts.xul b/browser/components/preferences/fonts.xul index 448d95e8d74a..6a32c45b0849 100644 --- a/browser/components/preferences/fonts.xul +++ b/browser/components/preferences/fonts.xul @@ -17,6 +17,7 @@ title="&fontsDialog.title;" dlgbuttons="accept,cancel,help" ondialoghelp="openPrefsHelp()" + onbeforeaccept="return gFontsDialog.onBeforeAccept();" style="">