diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm index 9ab4eb194409..c809f33f342c 100644 --- a/browser/components/customizableui/CustomizableUI.jsm +++ b/browser/components/customizableui/CustomizableUI.jsm @@ -300,6 +300,13 @@ let CustomizableUIInternal = { // We should still enter even if gSavedState.currentVersion >= kVersion // because the per-widget pref facility is independent of versioning. if (!gSavedState) { + // Flip all the prefs so we don't try to re-introduce later: + for (let [id, widget] of gPalette) { + if (widget.defaultArea && widget._introducedInVersion === "pref") { + let prefId = "browser.toolbarbuttons.introduced." + widget.id; + Services.prefs.setBoolPref(prefId, true); + } + } return; } diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index e8ee05d3e156..95c7aaa30938 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -175,28 +175,6 @@ const BOOKMARKS_BACKUP_MIN_INTERVAL_DAYS = 1; // days we will try to create a new one more aggressively. const BOOKMARKS_BACKUP_MAX_INTERVAL_DAYS = 3; -// Record the current default search engine in Telemetry. -function recordDefaultSearchEngine() { - let engine; - try { - engine = Services.search.defaultEngine; - } catch (e) {} - let name; - - if (!engine) { - name = "NONE"; - } else if (engine.identifier) { - name = engine.identifier; - } else if (engine.name) { - name = "other-" + engine.name; - } else { - name = "UNDEFINED"; - } - - let engines = Services.telemetry.getKeyedHistogramById("SEARCH_DEFAULT_ENGINE"); - engines.add(name, true) -} - // Factory object const BrowserGlueServiceFactory = { _instance: null, @@ -476,14 +454,12 @@ BrowserGlue.prototype = { ss.defaultEngine = ss.currentEngine; else ss.currentEngine = ss.defaultEngine; - recordDefaultSearchEngine(); break; case "browser-search-service": if (data != "init-complete") return; Services.obs.removeObserver(this, "browser-search-service"); this._syncSearchEngines(); - recordDefaultSearchEngine(); break; #ifdef NIGHTLY_BUILD case "nsPref:changed": diff --git a/browser/components/preferences/in-content/sync.js b/browser/components/preferences/in-content/sync.js index 230aa9a73463..18abb82beec2 100644 --- a/browser/components/preferences/in-content/sync.js +++ b/browser/components/preferences/in-content/sync.js @@ -570,7 +570,7 @@ let gSyncPane = { }, openChangeProfileImage: function() { - fxAccounts.promiseAccountsChangeProfileURI("avatar") + fxAccounts.promiseAccountsChangeProfileURI("preferences", "avatar") .then(url => { this.openContentInBrowser(url, { replaceQueryString: true @@ -579,7 +579,7 @@ let gSyncPane = { }, manageFirefoxAccount: function() { - fxAccounts.promiseAccountsManageURI() + fxAccounts.promiseAccountsManageURI("preferences") .then(url => { this.openContentInBrowser(url, { replaceQueryString: true diff --git a/browser/components/privatebrowsing/test/browser/browser.ini b/browser/components/privatebrowsing/test/browser/browser.ini index d0ee64575c9b..18bc27fafad3 100644 --- a/browser/components/privatebrowsing/test/browser/browser.ini +++ b/browser/components/privatebrowsing/test/browser/browser.ini @@ -17,9 +17,6 @@ support-files = [browser_privatebrowsing_DownloadLastDirWithCPS.js] [browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js] -skip-if = true # Bug 1142678 - Loading a message sending frame script into a private about:home tab causes leaks -[browser_privatebrowsing_aboutHomeButtonAfterWindowClose_old.js] -skip-if = e10s [browser_privatebrowsing_aboutSessionRestore.js] [browser_privatebrowsing_cache.js] [browser_privatebrowsing_certexceptionsui.js] diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose_old.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose_old.js deleted file mode 100644 index dc61c1e00191..000000000000 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_aboutHomeButtonAfterWindowClose_old.js +++ /dev/null @@ -1,50 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// This test checks that the Session Restore about:home button -// is disabled in private mode - -function test() { - waitForExplicitFinish(); - - function testNoSessionRestoreButton() { - let win = OpenBrowserWindow({private: true}); - win.addEventListener("load", function onLoad() { - win.removeEventListener("load", onLoad, false); - executeSoon(function() { - info("The second private window got loaded"); - let newTab = win.gBrowser.addTab(); - win.gBrowser.selectedTab = newTab; - let tabBrowser = win.gBrowser.getBrowserForTab(newTab); - tabBrowser.addEventListener("load", function tabLoadListener() { - if (win.content.location != "about:home") { - win.content.location = "about:home"; - return; - } - tabBrowser.removeEventListener("load", tabLoadListener, true); - executeSoon(function() { - info("about:home got loaded"); - let sessionRestoreButton = win.gBrowser - .contentDocument - .getElementById("restorePreviousSession"); - is(win.getComputedStyle(sessionRestoreButton).display, - "none", "The Session Restore about:home button should be disabled"); - win.close(); - finish(); - }); - }, true); - }); - }, false); - } - - let win = OpenBrowserWindow({private: true}); - win.addEventListener("load", function onload() { - win.removeEventListener("load", onload, false); - executeSoon(function() { - info("The first private window got loaded"); - win.close(); - testNoSessionRestoreButton(); - }); - }, false); -} diff --git a/browser/components/sessionstore/test/browser.ini b/browser/components/sessionstore/test/browser.ini index 1eacb57ff6aa..bb289fa8d893 100644 --- a/browser/components/sessionstore/test/browser.ini +++ b/browser/components/sessionstore/test/browser.ini @@ -96,8 +96,6 @@ skip-if = buildapp == 'mulet' [browser_restore_redirect.js] [browser_scrollPositions.js] [browser_sessionHistory.js] -# Disabled because of bug 1077581 -skip-if = e10s [browser_sessionStorage.js] [browser_swapDocShells.js] skip-if = e10s # See bug 918634 diff --git a/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js b/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js index 81fbbfb9df6b..21fe13a00275 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_add-rule_01.js @@ -22,7 +22,7 @@ let PAGE_CONTENT = [ const TEST_DATA = [ { node: "#testid", expected: "#testid" }, { node: ".testclass2", expected: ".testclass2" }, - { node: ".class1.class2", expected: ".class1" }, + { node: ".class1.class2", expected: ".class1.class2" }, { node: "p", expected: "p" } ]; @@ -95,4 +95,4 @@ function* testNewRule(view, expected, index) { let lastRule = textProps[textProps.length - 1]; is(lastRule.name, "font-weight", "Last rule name is font-weight"); is(lastRule.value, "bold", "Last rule value is bold"); -} \ No newline at end of file +} diff --git a/browser/locales/en-US/searchplugins/ddg.xml b/browser/locales/en-US/searchplugins/ddg.xml index d68deb4b0df5..46f12792fec5 100644 --- a/browser/locales/en-US/searchplugins/ddg.xml +++ b/browser/locales/en-US/searchplugins/ddg.xml @@ -6,7 +6,7 @@ data:image/icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAEAAATCwAAEwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA11RgALs6oACbQ9wAj0v8AI9L/ACfQ9wAu0agANdUYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzzN4CNdL/oK/z//////////////////////+jsPv/BDXX/wAz0t4AAAAAAAAAAAAAAAAAAAAAAAAAAAAyzvNSduD//////8jK/v+P+Lf/IbQL/17RPP+J3Y//wOKX//////9YeuX/ADLO8wAAAAAAAAAAAAAAAAAw091piOX/8/X9/1Fx5P9xhu//WOWZ/0W9Lv9Lwjn/J8BB/xyDAP9bdfL/9fP//2mI5v8AMNPdAAAAAAc610YRQ9f//////0Zr4P8AGdD/sb32////////////wrv//wAh1/8MPab/ACPc/05r4///////EkPX/wc610YANtWkrr/y/6S48P8AJ9L/AB3R/+/w/v///////////3+D7f8AQeL/AYTw/wFr5/8AMNb/p7Tv/6698v8AM9WkADLW//////8yXt//AC3V/wAw1/////////////z///8A0P7/AKb1/wWI7P8AuPf/AJ3w/zZW3P//////ADHV/wAx2P//////AzrZ/wAu1/84ZOL////////////e////AND//wC1+f8Atff/AZbv/wY62f8ELNf//////wAw1/8AMtn//////wAw2f8ALNn/kKrz////+//cwbH////////////R////Rcb8/wDO/f8A/P//AHzo//////8AMNj/ADXa//////8vXuL/ACna/4yq9///79T/jUkg/9i+r///////r2Q0/7Cozv8BKdr/AirY/zdZ4P//////ADTa/wI72tOuv/T/prr0/wAl2v+JqPb//7yW/+bUxv/9+/n////u//W+n/+Op/L/ADPd/wAv2v+ru/T/r7/0/wI72tMLQd1DEEjg//////9Cbef/ADng///////////////////////R3///AC3g/wAy3v9SeOn//////xFI4P8LQd1DAAAAAAM64PNmiuz/9/j//2mN7f/m7P3///////////9Cb+n/ACXd/wAt3v9rju3//////2iL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/P8J0vz/ELDz/xt85v8mSdj/JknY/yZJ2P8lStowJUjXYCZJ2P8nSdhwJErZryZK2f8oSNcgJUnajyZK2f8mStn/JkrZ/yZK2f8mStn/iJPA////////////////////////////0ff+/xjV/P8J0vz/Drn1/xiO6/8Yjuv/GI7r/xCw8/8Lyvr/CdL8/xmF6P8mStn/JkrZ/yVJ2o8oSNcgJkrZ/yRK2a8jStrfI0rZ3wAAAAAlSdq/Jkra/yZK2v8mStr/Jkra/yZK2v+xtsf///////////////////////////8o2Pz/CdL8/wvK+v8mStr/Jkra/yZK2v8mStr/Jkra/yZK2v8iW97/Jkra/yZK2v8mStr/JUnavwAAAAAjStnfI0ra3yZK2v8lSdq/AAAAACZH2O8mStr/Jkra/yZK2v8mStr/L1HY/9HR0f///////////////////////////yjY/P8J0vz/CdL8/xCw9P8QsPT/ELD0/xSf7/8ddeX/Jkra/yZK2v8mStr/Jkra/yZK2v8mR9jvAAAAACVJ2r8mStr/Jkvb/yVJ2r8AAAAAJkvb/yZL2/8mS9v/Jkvb/yZL2/9KZtL/4+Pj////////////////////////////4Pn//0fd/f8J0vz/CdL8/wnS/P8J0vz/CdL8/wnS/P8Lyvr/Fpfu/yJc3/8mS9v/Jkvb/yZL2/8AAAAAJUnavyZL2/8mS9z/JUncvwAAAAAmS9z/Jkvc/yZL3P8mS9z/Jkvc/26AyP/x8fH//////////////////////////////////////9H3/v/C9P7/o+7+/2fa+/8Oufb/CdL8/wnS/P8J0vz/CdL8/xiP7P8mS9z/Jkvc/wAAAAAlSdy/Jkvc/yZM3P8lTNy/AAAAACZJ2e8mTNz/Jkzc/yZM3P8mTNz/iJTB////////////qnth/5VaOf/x6eX///////////////////////Hp5f/x6eX/ydL2/yZM3P8kVN7/G37o/xKo8v8QsfT/HXbm/yZM3P8mSdnvAAAAACVM3L8mTNz/I0vc3yZJ2u8AAAAAJUzevyZM3f8mTN3/Jkzd/yZM3f+fqc3///////////+VWjn/v5yI/+re1///////////////////////jk8s/7iRe//J0vb/Jkzd/yZM3f8mTN3/Jkzd/yZM3f8mTN3/Jkzd/yVM3r8AAAAAI0vc3yNL3N8kTd2vJk3d/yhQ3yAlTd2PJk3d/yZN3f8mTd3/Jk3d/6St0v////////////Hp5f/q3tf///////////////////////////+xhm7/49PK/6Cx8P8mTd3/Jk3d/yZN3f8mTd3/Jk3d/yZN3f8mTd3/JU3djyhQ3yAmTd3/JE3drydN33AmTd7/J03fcCVK3zAmTd7/Jk3e/yZN3v8mTd7/pK7S///////Sp5r/////////////////////////////////////////////////T27k/yZN3v8mTd7/Jk3e/yZN3v8mTd7/Jk3e/yZN3v8lSt8wJ03fcCZN3v8nTd9wKFDfICZO3/8mTt3PAAAAACVN3r8mTt//Jk7f/yZO3/+EltX//////+fRyv/SqaD/59LO///////////////////////at63/vIBy/7Glxf8mTt//Jk7f/yZO3/8mTt//Jk7f/yZO3/8mTt//JU3evwAAAAAmTt3PJk7f/yhQ3yAAAAAAJE/dryZO3/8oUN9AKFDfQCZO3/8mTt//Jk7f/zhb2v/o6/T/////////////////////////////////////////////////XHrn/yZO3/8mTt//Jk7f/yZO3/8mTt//Jk7f/yZO3/8oUN9AKFDfQCZO3/8kT92vAAAAAAAAAAAoUN9AJk7g/yZO4M8AAAAAJk/hnyZO4P8mTuD/Jk7g/05v5v/k6fv//////////////////////////////////////3eR7P8mTuD/Jk7g/yZO4P8mTuD/Jk7g/yZO4P8mTuD/Jk/hnwAAAAAmTuDPJk7g/yhQ30AAAAAAAAAAAAAAAAAjT+GfJU/h/yVO4Y8gUN8QIk7gzyVP4f8lT+H/SWnW/0lp1v+bq+H/8fHx/////////////////6Cy8v9OcOb/JU/h/yVP4f8lT+H/JU/h/yVP4f8lT+H/JU/h/yJO4M8gUN8QJU7hjyVP4f8jT+GfAAAAAAAAAAAAAAAAAAAAACBQ3xAlTOHvJU/h/yVQ4mAgUN8QIk7hzyVP4f+ktOv///////////////////////H0/f9phur/JU/h/yVP4f8lT+H/JU/h/yVP4f8lT+H/JU/h/yVP4f8iTuHPIFDfECVQ4mAlT+H/JUzh7yBQ3xAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ3zAlUOLvJVDi/yVQ4mAgUN8QI1Din4mb2//J0/j/ydP4/6299P93ku3/M1vk/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/I1DinyBQ3xAlUOJgJVDi/yVQ4u8lUN8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ5DAlUOLvJVDi/yVQ4o8AAAAAJFDjQCVQ4r8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDi/yVQ4v8lUOL/JVDivyRQ40AAAAAAJVDijyVQ4v8lUOLvJVDkMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQ5DAjUeTfJVHj/yNR5N8kUONAAAAAACVQ5DAmUuOAJVHivyNR5N8lUeP/JVHj/yNR5N8lUeK/JlLjgCVQ5DAAAAAAJFDjQCNR5N8lUeP/I1Hk3yVQ5DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBQ3xAjUuSfJVHk/yVR5P8jUeTfJFLkcChQ5yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoUOcgJFLkcCNR5N8lUeT/JVHk/yNS5J8gUN8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkUONAI1LknyVS5P8lUuT/JVLk/yVS5O8lUeS/JVHkvyVR5L8lUeS/JVLk7yVS5P8lUuT/JVLk/yRS468kUONAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFDfECVS5GAjUuWfIlPlzyVS5f8lUuX/JVLl/yVS5f8iU+XPI1LlnyVS5GAgUN8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/AA///AAD//AAAP/ggBB/wgAEP4AAAB8AAAAPAAAADiAAAEYAAAAEQAAAIAAAAAAAAAAAgAAAEIAAABCAAAAQgAAAEIAAABCAAAAQAAAAAAAAAABAAAAiAAAABiAAAEcAAAAPAAAAD4AAAB/CAAQ/4IAQf/AfgP/8AAP//wAP/ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAAAaCAYAAADovjFxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxNTg5QTM3RjNCMjA2ODExODIyQUVEOUNBRDIxQzhDMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxRTYyNzYzMzFBQUUxMUU0ODc3NTg3NjMyNDFCNzExQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxRTYyNzYzMjFBQUUxMUU0ODc3NTg3NjMyNDFCNzExQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDE4MDExNzQwNzIwNjgxMTg3MUZCQUIxMEI4RjU1NzYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MTU4OUEzN0YzQjIwNjgxMTgyMkFFRDlDQUQyMUM4QzMiLz4gPC9yZGY6RGVzY3Jp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 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAAA0CAYAAABGkOCVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDoxNTg5QTM3RjNCMjA2ODExODIyQUVEOUNBRDIxQzhDMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4RTdBNDY4ODFBQUQxMUU0ODc3NTg3NjMyNDFCNzExQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4RTdBNDY4NzFBQUQxMUU0ODc3NTg3NjMyNDFCNzExQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTE3MzgzQ0I2QjIwNjgxMTgyMkFFRDlDQUQyMUM4QzMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MTU4OUEzN0YzQjIwNjgxMTgyMkFFRDlDQUQyMUM4QzMiLz4gPC9yZGY6RGVzY3Jp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 - + diff --git a/layout/base/PositionedEventTargeting.cpp b/layout/base/PositionedEventTargeting.cpp index 078986e728f2..409f0f907378 100644 --- a/layout/base/PositionedEventTargeting.cpp +++ b/layout/base/PositionedEventTargeting.cpp @@ -76,7 +76,7 @@ struct EventRadiusPrefs bool mRegistered; bool mTouchOnly; bool mRepositionEventCoords; - bool mTouchClusterDetection; + bool mTouchClusterDetectionDisabled; uint32_t mLimitReadableSize; }; @@ -125,8 +125,8 @@ GetPrefsFor(EventClassID aEventClassID) nsPrintfCString repositionPref("ui.%s.radius.reposition", prefBranch); Preferences::AddBoolVarCache(&prefs->mRepositionEventCoords, repositionPref.get(), false); - nsPrintfCString touchClusterPref("ui.zoomedview.enabled", prefBranch); - Preferences::AddBoolVarCache(&prefs->mTouchClusterDetection, touchClusterPref.get(), false); + nsPrintfCString touchClusterPref("ui.zoomedview.disabled", prefBranch); + Preferences::AddBoolVarCache(&prefs->mTouchClusterDetectionDisabled, touchClusterPref.get(), true); nsPrintfCString limitReadableSizePref("ui.zoomedview.limitReadableSize", prefBranch); Preferences::AddUintVarCache(&prefs->mLimitReadableSize, limitReadableSizePref.get(), 8); @@ -396,7 +396,7 @@ GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame, static bool IsElementClickableAndReadable(nsIFrame* aFrame, WidgetGUIEvent* aEvent, const EventRadiusPrefs* aPrefs) { - if (!aPrefs->mTouchClusterDetection) { + if (aPrefs->mTouchClusterDetectionDisabled) { return true; } @@ -487,7 +487,7 @@ FindFrameTargetedByInputEvent(WidgetGUIEvent* aEvent, GetClosest(aRootFrame, aPointRelativeToRootFrame, targetRect, prefs, restrictToDescendants, candidates, &elementsInCluster); if (closestClickable) { - if ((prefs->mTouchClusterDetection && elementsInCluster > 1) || + if ((!prefs->mTouchClusterDetectionDisabled && elementsInCluster > 1) || (!IsElementClickableAndReadable(closestClickable, aEvent, prefs))) { if (aEvent->mClass == eMouseEventClass) { WidgetMouseEventBase* mouseEventBase = aEvent->AsMouseEventBase(); diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 5d14c9f80892..f7cc4a62af02 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -403,7 +403,7 @@ pref("font.size.inflation.minTwips", 0); // When true, zooming will be enabled on all sites, even ones that declare user-scalable=no. pref("browser.ui.zoom.force-user-scalable", false); -pref("ui.zoomedview.enabled", false); +pref("ui.zoomedview.disabled", false); pref("ui.zoomedview.limitReadableSize", 8); // value in layer pixels pref("ui.touch.radius.enabled", false); diff --git a/mobile/android/tests/browser/robocop/testOfflinePage.js b/mobile/android/tests/browser/robocop/testOfflinePage.js index b29d03cba6e1..71b206085ddb 100644 --- a/mobile/android/tests/browser/robocop/testOfflinePage.js +++ b/mobile/android/tests/browser/robocop/testOfflinePage.js @@ -18,6 +18,37 @@ function is(lhs, rhs, text) { do_report_result(lhs === rhs, text, Components.stack.caller, false); } +function promiseBrowserEvent(browser, eventType) { + return new Promise((resolve) => { + function handle(event) { + // Since we'll be redirecting, don't make assumptions about the given URL and the loaded URL + if (event.target != browser.contentDocument || event.target.location.href == "about:blank") { + do_print("Skipping spurious '" + eventType + "' event" + " for " + event.target.location.href); + return; + } + do_print("Received event " + eventType + " from browser"); + browser.removeEventListener(eventType, handle, true); + resolve(event); + } + + browser.addEventListener(eventType, handle, true); + do_print("Now waiting for " + eventType + " event from browser"); + }); +} + +// Provide a helper to yield until we are sure the offline state has changed +function promiseOffline(isOffline) { + return new Promise((resolve, reject) => { + function observe(subject, topic, data) { + do_print("Received topic: " + topic); + Services.obs.removeObserver(observe, "network:offline-status-changed"); + resolve(); + } + Services.obs.addObserver(observe, "network:offline-status-changed", false); + Services.io.offline = isOffline; + }); +} + // The chrome window let chromeWin; @@ -29,7 +60,7 @@ let proxyPrefValue; const kUniqueURI = Services.io.newURI("http://mochi.test:8888/tests/robocop/video_controls.html", null, null); -add_test(function setup_browser() { +add_task(function* test_offline() { // Tests always connect to localhost, and per bug 87717, localhost is now // reachable in offline mode. To avoid this, disable any proxy. proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); @@ -47,29 +78,15 @@ add_test(function setup_browser() { Services.io.offline = false; }); - do_test_pending(); - // Add a new tab with a blank page so we can better control the real page load and the offline state browser = BrowserApp.addTab("about:blank", { selected: true, parentId: BrowserApp.selectedTab.id }).browser; // Go offline, expecting the error page. - Services.io.offline = true; + yield promiseOffline(true); // Load our test web page - browser.addEventListener("DOMContentLoaded", errorListener, true); browser.loadURI(kUniqueURI.spec, null, null) -}); - -//------------------------------------------------------------------------------ -// listen to loading the neterror page. (offline mode) -function errorListener() { - if (browser.contentWindow.location == "about:blank") { - do_print("got about:blank, which is expected once, so return"); - return; - } - - browser.removeEventListener("DOMContentLoaded", errorListener, true); - ok(Services.io.offline, "Services.io.offline is true."); + yield promiseBrowserEvent(browser, "DOMContentLoaded"); // This is an error page. is(browser.contentDocument.documentURI.substring(0, 27), "about:neterror?e=netOffline", "Document URI is the error page."); @@ -79,29 +96,17 @@ function errorListener() { Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); - // Now press the "Try Again" button, with offline mode off. - Services.io.offline = false; - - browser.addEventListener("DOMContentLoaded", reloadListener, true); + // Go online and try to load the page again + yield promiseOffline(false); ok(browser.contentDocument.getElementById("errorTryAgain"), "The error page has got a #errorTryAgain element"); + + // Click "Try Again" button to start the page load browser.contentDocument.getElementById("errorTryAgain").click(); -} - - -//------------------------------------------------------------------------------ -// listen to reload of neterror. -function reloadListener() { - browser.removeEventListener("DOMContentLoaded", reloadListener, true); - - ok(!Services.io.offline, "Services.io.offline is false."); + yield promiseBrowserEvent(browser, "DOMContentLoaded"); // This is not an error page. is(browser.contentDocument.documentURI, kUniqueURI.spec, "Document URI is not the offline-error page, but the original URI."); - - do_test_finished(); - - run_next_test(); -} +}); run_next_test(); diff --git a/services/fxaccounts/FxAccounts.jsm b/services/fxaccounts/FxAccounts.jsm index d5de2fb17750..a7997c4187d0 100644 --- a/services/fxaccounts/FxAccounts.jsm +++ b/services/fxaccounts/FxAccounts.jsm @@ -1200,7 +1200,7 @@ FxAccountsInternal.prototype = { // the current account's profile image. // if settingToEdit is set, the profile page should hightlight that setting // for the user to edit. - promiseAccountsChangeProfileURI: function(settingToEdit = null) { + promiseAccountsChangeProfileURI: function(entrypoint, settingToEdit = null) { let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.settings.uri"); if (settingToEdit) { @@ -1220,13 +1220,16 @@ FxAccountsInternal.prototype = { let newQueryPortion = url.indexOf("?") == -1 ? "?" : "&"; newQueryPortion += "email=" + encodeURIComponent(accountData.email); newQueryPortion += "&uid=" + encodeURIComponent(accountData.uid); + if (entrypoint) { + newQueryPortion += "&entrypoint=" + encodeURIComponent(entrypoint); + } return url + newQueryPortion; }).then(result => currentState.resolve(result)); }, // Returns a promise that resolves with the URL to use to manage the current // user's FxA acct. - promiseAccountsManageURI: function() { + promiseAccountsManageURI: function(entrypoint) { let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.settings.uri"); if (this._requireHttps() && !/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting throw new Error("Firefox Accounts server must use HTTPS"); @@ -1242,6 +1245,9 @@ FxAccountsInternal.prototype = { let newQueryPortion = url.indexOf("?") == -1 ? "?" : "&"; newQueryPortion += "uid=" + encodeURIComponent(accountData.uid) + "&email=" + encodeURIComponent(accountData.email); + if (entrypoint) { + newQueryPortion += "&entrypoint=" + encodeURIComponent(entrypoint); + } return url + newQueryPortion; }).then(result => currentState.resolve(result)); }, diff --git a/toolkit/components/search/nsSearchService.js b/toolkit/components/search/nsSearchService.js index c5163cde2dff..4e62d713cd8f 100644 --- a/toolkit/components/search/nsSearchService.js +++ b/toolkit/components/search/nsSearchService.js @@ -2861,10 +2861,14 @@ Engine.prototype = { }, get searchForm() { + return this._getSearchFormWithPurpose(); + }, + + _getSearchFormWithPurpose(aPurpose = "") { // First look for a var searchFormURL = this._getURLOfType(URLTYPE_SEARCH_HTML, "searchform"); if (searchFormURL) { - let submission = searchFormURL.getSubmission("", this); + let submission = searchFormURL.getSubmission("", this, aPurpose); // If the rel=searchform URL is not type="get" (i.e. has postData), // ignore it, since we can only return a URL. @@ -2947,7 +2951,7 @@ Engine.prototype = { if (!aData) { // Return a dummy submission object with our searchForm attribute - return new Submission(makeURI(this.searchForm), null); + return new Submission(makeURI(this._getSearchFormWithPurpose(aPurpose)), null); } LOG("getSubmission: In data: \"" + aData + "\"; Purpose: \"" + aPurpose + "\""); diff --git a/toolkit/components/search/tests/xpcshell/data/engine-rel-searchform-purpose.xml b/toolkit/components/search/tests/xpcshell/data/engine-rel-searchform-purpose.xml new file mode 100644 index 000000000000..18026210fcc8 --- /dev/null +++ b/toolkit/components/search/tests/xpcshell/data/engine-rel-searchform-purpose.xml @@ -0,0 +1,11 @@ + + +engine-rel-searchform-purpose + + + + + + + + diff --git a/toolkit/components/search/tests/xpcshell/test_purpose.js b/toolkit/components/search/tests/xpcshell/test_purpose.js index 107e9fbb8127..56c26de8a06f 100644 --- a/toolkit/components/search/tests/xpcshell/test_purpose.js +++ b/toolkit/components/search/tests/xpcshell/test_purpose.js @@ -46,5 +46,13 @@ add_task(function* test_purpose() { check_submission("&channel=fflb", "foo", "application/x-moz-default-purpose", "keyword"); check_submission("", "foo", "application/x-moz-default-purpose", "invalid"); + // Tests for a purpose on the search form (ie. empty query). + [engine] = yield addTestEngines([ + { name: "engine-rel-searchform-purpose", xmlFileName: "engine-rel-searchform-purpose.xml" } + ]); + base = "http://www.google.com/search?q="; + check_submission("&channel=sb", "", null, "searchbar"); + check_submission("&channel=sb", "", "text/html", "searchbar"); + do_test_finished(); }); diff --git a/toolkit/components/search/tests/xpcshell/xpcshell.ini b/toolkit/components/search/tests/xpcshell/xpcshell.ini index e08e931fb6b3..2cc53dcc002a 100644 --- a/toolkit/components/search/tests/xpcshell/xpcshell.ini +++ b/toolkit/components/search/tests/xpcshell/xpcshell.ini @@ -13,6 +13,7 @@ support-files = data/engineMaker.sjs data/engine-rel-searchform.xml data/engine-rel-searchform-post.xml + data/engine-rel-searchform-purpose.xml data/engineImages.xml data/ico-size-16x16-png.ico data/invalid-engine.xml diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 14941b93f9c4..f698c28d3852 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -4722,13 +4722,6 @@ "releaseChannelCollection": "opt-out", "description": "Record the search counts for search engines" }, - "SEARCH_DEFAULT_ENGINE": { - "expires_in_version": "never", - "kind": "flag", - "keyed": true, - "releaseChannelCollection": "opt-out", - "description": "Record the default search engine." - }, "SEARCH_SERVICE_INIT_MS": { "expires_in_version": "never", "kind": "exponential", diff --git a/toolkit/components/telemetry/TelemetryController.jsm b/toolkit/components/telemetry/TelemetryController.jsm index 795e740e160e..183e190c9e40 100644 --- a/toolkit/components/telemetry/TelemetryController.jsm +++ b/toolkit/components/telemetry/TelemetryController.jsm @@ -24,6 +24,8 @@ Cu.import("resource://gre/modules/Preferences.jsm"); Cu.import("resource://gre/modules/Timer.jsm"); Cu.import("resource://gre/modules/TelemetryUtils.jsm", this); +const Utils = TelemetryUtils; + const LOGGER_NAME = "Toolkit.Telemetry"; const LOGGER_PREFIX = "TelemetryController::"; @@ -52,12 +54,11 @@ const TELEMETRY_TEST_DELAY = 100; // Timeout after which we consider a ping submission failed. const PING_SUBMIT_TIMEOUT_MS = 2 * 60 * 1000; -// We treat pings before midnight as happening "at midnight" with this tolerance. -const MIDNIGHT_TOLERANCE_MS = 15 * 60 * 1000; // For midnight fuzzing we want to affect pings around midnight with this tolerance. const MIDNIGHT_TOLERANCE_FUZZ_MS = 5 * 60 * 1000; // We try to spread "midnight" pings out over this interval. const MIDNIGHT_FUZZING_INTERVAL_MS = 60 * 60 * 1000; +// We delay sending "midnight" pings on this client by this interval. const MIDNIGHT_FUZZING_DELAY_MS = Math.random() * MIDNIGHT_FUZZING_INTERVAL_MS; // Ping types. @@ -532,7 +533,16 @@ let Impl = { * @return Number The next time (ms from UNIX epoch) when we can send pings. */ _getNextPingSendTime: function(now) { - const midnight = TelemetryUtils.getNearestMidnight(now, MIDNIGHT_FUZZING_INTERVAL_MS); + // 1. First we check if the time is between 11pm and 1am. If it's not, we send + // immediately. + // 2. If we confirmed the time is indeed between 11pm and 1am in step 1, we + // then check if the time is also 11:55pm or later. If it's not, we send + // immediately. + // 3. Finally, if the time is between 11:55pm and 1am, we disallow sending + // before (midnight + fuzzing delay), which is a random time between 12am-1am + // (decided at startup). + + const midnight = Utils.getNearestMidnight(now, MIDNIGHT_FUZZING_INTERVAL_MS); // Don't delay ping if we are not close to midnight. if (!midnight) { diff --git a/toolkit/components/telemetry/TelemetryEnvironment.jsm b/toolkit/components/telemetry/TelemetryEnvironment.jsm index a1e047ed313a..546cd8704065 100644 --- a/toolkit/components/telemetry/TelemetryEnvironment.jsm +++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm @@ -154,6 +154,8 @@ const PREF_UPDATE_AUTODOWNLOAD = "app.update.auto"; const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed"; +const SEARCH_ENGINE_MODIFIED_TOPIC = "browser-search-engine-modified"; +const SEARCH_SERVICE_TOPIC = "browser-search-service"; /** * Turn a millisecond timestamp into a day timestamp. @@ -651,6 +653,8 @@ function EnvironmentCache() { }; this._updateSettings(); + // Fill in the default search engine, if the search provider is already initialized. + this._updateSearchEngine(); // Build the remaining asynchronous parts of the environment. Don't register change listeners // until the initial environment has been built. @@ -663,21 +667,21 @@ function EnvironmentCache() { p.push(this._updateProfile()); #endif + let setup = () => { + this._initTask = null; + this._startWatchingPrefs(); + this._addonBuilder.watchForChanges(); + this._addObservers(); + return this.currentEnvironment; + }; + this._initTask = Promise.all(p) .then( - () => { - this._initTask = null; - this._startWatchingPrefs(); - this._addonBuilder.watchForChanges(); - return this.currentEnvironment; - }, + () => setup(), (err) => { // log errors but eat them for consumers this._log.error("EnvironmentCache - error while initializing", err); - this._initTask = null; - this._startWatchingPrefs(); - this._addonBuilder.watchForChanges(); - return this.currentEnvironment; + return setup(); }); } EnvironmentCache.prototype = { @@ -799,6 +803,90 @@ EnvironmentCache.prototype = { } }, + _addObservers: function () { + // Watch the search engine change and service topics. + Services.obs.addObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC, false); + Services.obs.addObserver(this, SEARCH_SERVICE_TOPIC, false); + }, + + _removeObservers: function () { + // Remove the search engine change and service observers. + Services.obs.removeObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC); + Services.obs.removeObserver(this, SEARCH_SERVICE_TOPIC); + }, + + observe: function (aSubject, aTopic, aData) { + this._log.trace("observe - aTopic: " + aTopic + ", aData: " + aData); + switch (aTopic) { + case SEARCH_ENGINE_MODIFIED_TOPIC: + if (aData != "engine-default" && aData != "engine-current") { + return; + } + // Record the new default search choice and send the change notification. + this._onSearchEngineChange(); + break; + case SEARCH_SERVICE_TOPIC: + if (aData != "init-complete") { + return; + } + // Now that the search engine init is complete, record the default search choice. + this._updateSearchEngine(); + break; + } + }, + + /** + * Get the default search engine. + * @return {String} Returns the search engine identifier, "NONE" if no default search + * engine is defined or "UNDEFINED" if no engine identifier or name can be found. + */ + _getDefaultSearchEngine: function () { + let engine; + try { + engine = Services.search.defaultEngine; + } catch (e) {} + + let name; + if (!engine) { + name = "NONE"; + } else if (engine.identifier) { + name = engine.identifier; + } else if (engine.name) { + name = "other-" + engine.name; + } else { + name = "UNDEFINED"; + } + + return name; + }, + + /** + * Update the default search engine value. + */ + _updateSearchEngine: function () { + this._log.trace("_updateSearchEngine - isInitialized: " + Services.search.isInitialized); + if (!Services.search.isInitialized) { + return; + } + + // Make sure we have a settings section. + this._currentEnvironment.settings = this._currentEnvironment.settings || {}; + // Update the search engine entry in the current environment. + this._currentEnvironment.settings.defaultSearchEngine = this._getDefaultSearchEngine(); + }, + + /** + * Update the default search engine value and trigger the environment change. + */ + _onSearchEngineChange: function () { + this._log.trace("_onSearchEngineChange"); + + // Finally trigger the environment change notification. + let oldEnvironment = Cu.cloneInto(this._currentEnvironment, myScope); + this._updateSearchEngine(); + this._onEnvironmentChange("search-engine-changed", oldEnvironment); + }, + /** * Get the build data in object form. * @return Object containing the build data. diff --git a/toolkit/components/telemetry/TelemetrySession.jsm b/toolkit/components/telemetry/TelemetrySession.jsm index 549fa478d6c1..82f20e2702b1 100644 --- a/toolkit/components/telemetry/TelemetrySession.jsm +++ b/toolkit/components/telemetry/TelemetrySession.jsm @@ -22,6 +22,8 @@ Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/Timer.jsm"); Cu.import("resource://gre/modules/TelemetryUtils.jsm", this); +const Utils = TelemetryUtils; + const myScope = this; const IS_CONTENT_PROCESS = (function() { @@ -424,7 +426,7 @@ let TelemetryScheduler = { timeout = SCHEDULER_TICK_IDLE_INTERVAL_MS; // We need to make sure though that we don't miss sending pings around // midnight when we use the longer idle intervals. - const nextMidnight = TelemetryUtils.getNextMidnight(now); + const nextMidnight = Utils.getNextMidnight(now); timeout = Math.min(timeout, nextMidnight.getTime() - now.getTime()); } @@ -435,8 +437,8 @@ let TelemetryScheduler = { _sentDailyPingToday: function(nowDate) { // This is today's date and also the previous midnight (0:00). - const todayDate = TelemetryUtils.truncateToDays(nowDate); - const nearestMidnight = TelemetryUtils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); + const todayDate = Utils.truncateToDays(nowDate); + const nearestMidnight = Utils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); // If we are close to midnight, we check against that, otherwise against the last midnight. const checkDate = nearestMidnight || todayDate; // We consider a ping sent for today if it occured after midnight, or prior within the tolerance. @@ -457,7 +459,7 @@ let TelemetryScheduler = { return false; } - const nearestMidnight = TelemetryUtils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); + const nearestMidnight = Utils.getNearestMidnight(nowDate, SCHEDULER_MIDNIGHT_TOLERANCE_MS); if (!sentPingToday && !nearestMidnight) { // Computer must have gone to sleep, the daily ping is overdue. this._log.trace("_isDailyPingDue - daily ping is overdue... computer went to sleep?"); @@ -567,7 +569,7 @@ let TelemetryScheduler = { let nextSessionCheckpoint = this._lastSessionCheckpointTime + ABORTED_SESSION_UPDATE_INTERVAL_MS; let combineActions = (shouldSendDaily && isAbortedPingDue) || (shouldSendDaily && - TelemetryUtils.areTimesClose(now, nextSessionCheckpoint, + Utils.areTimesClose(now, nextSessionCheckpoint, SCHEDULER_COALESCE_THRESHOLD_MS)); if (combineActions) { @@ -613,7 +615,7 @@ let TelemetryScheduler = { // update the schedules. this._saveAbortedPing(now.getTime(), competingPayload); // If we're close to midnight, skip today's daily ping and reschedule it for tomorrow. - let nearestMidnight = TelemetryUtils.getNearestMidnight(now, SCHEDULER_MIDNIGHT_TOLERANCE_MS); + let nearestMidnight = Utils.getNearestMidnight(now, SCHEDULER_MIDNIGHT_TOLERANCE_MS); if (nearestMidnight) { this._lastDailyPingTime = now.getTime(); } @@ -1102,8 +1104,8 @@ let Impl = { getMetadata: function getMetadata(reason) { this._log.trace("getMetadata - Reason " + reason); - let sessionStartDate = toLocalTimeISOString(TelemetryUtils.truncateToDays(this._sessionStartDate)); - let subsessionStartDate = toLocalTimeISOString(TelemetryUtils.truncateToDays(this._subsessionStartDate)); + let sessionStartDate = toLocalTimeISOString(Utils.truncateToDays(this._sessionStartDate)); + let subsessionStartDate = toLocalTimeISOString(Utils.truncateToDays(this._subsessionStartDate)); // Compute the subsession length in milliseconds, then convert to seconds. let subsessionLength = Math.floor((Policy.now() - this._subsessionStartDate.getTime()) / 1000); diff --git a/toolkit/components/telemetry/TelemetryStorage.jsm b/toolkit/components/telemetry/TelemetryStorage.jsm index 6474128bc6e1..8f3f07dbac20 100644 --- a/toolkit/components/telemetry/TelemetryStorage.jsm +++ b/toolkit/components/telemetry/TelemetryStorage.jsm @@ -1029,8 +1029,8 @@ let TelemetryStorageImpl = { removeAbortedSessionPing: function() { return this._abortedSessionSerializer.enqueueTask(Task.async(function*() { try { + yield OS.File.remove(gAbortedSessionFilePath, { ignoreAbsent: false }); this._log.trace("removeAbortedSessionPing - success"); - yield OS.File.remove(gAbortedSessionFilePath); } catch (ex if ex.becauseNoSuchFile) { this._log.trace("removeAbortedSessionPing - no such file"); } catch (ex) { diff --git a/toolkit/components/telemetry/docs/environment.rst b/toolkit/components/telemetry/docs/environment.rst index 201553403fca..2471fc673508 100644 --- a/toolkit/components/telemetry/docs/environment.rst +++ b/toolkit/components/telemetry/docs/environment.rst @@ -34,6 +34,7 @@ Structure:: settings: { blocklistEnabled: , // true on failure isDefaultBrowser: , // null on failure, not available on Android + defaultSearchEngine: , // e.g. "yahoo" e10sEnabled: , // false on failure telemetryEnabled: , // false on failure locale: , // e.g. "it", null on failure @@ -189,3 +190,16 @@ Structure:: persona: , // id of the current persona, null on GONK }, } + +Settings +-------- + +defaultSearchEngine +~~~~~~~~~~~~~~~~~~~ +Contains the string identifier or name of the default search engine provider. This will not be present in environment data collected before the Search Service initialization. + +The special value ``NONE`` could occur if there is no default search engine. + +The special value ``UNDEFINED`` could occur if a default search engine exists but its identifier could not be determined. + +This field's contents are ``Services.search.defaultEngine.identifier`` (if defined) or ``"other-"`` + ``Services.search.defaultEngine.name`` if not. In other words, search engines without an ``.identifier`` are prefixed with ``other-``. diff --git a/toolkit/components/telemetry/tests/search/chrome.manifest b/toolkit/components/telemetry/tests/search/chrome.manifest new file mode 100644 index 000000000000..ec412e05081f --- /dev/null +++ b/toolkit/components/telemetry/tests/search/chrome.manifest @@ -0,0 +1,3 @@ +locale testsearchplugin ar jar:jar:searchTest.jar!/chrome/searchTest.jar!/ +content testsearchplugin ./ + diff --git a/toolkit/components/telemetry/tests/search/searchTest.jar b/toolkit/components/telemetry/tests/search/searchTest.jar new file mode 100644 index 000000000000..b10fc0c3eca3 Binary files /dev/null and b/toolkit/components/telemetry/tests/search/searchTest.jar differ diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js index 2ce0c1846b70..7ac570ba98b5 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js @@ -280,6 +280,11 @@ function checkSettingsSection(data) { Assert.ok(checkNullOrString(update.channel)); Assert.equal(typeof update.enabled, "boolean"); Assert.equal(typeof update.autoDownload, "boolean"); + + // Check "defaultSearchEngine" separately, as it can either be undefined or string. + if ("defaultSearchEngine" in data.settings) { + checkString(data.settings.defaultSearchEngine); + } } function checkProfileSection(data) { @@ -561,6 +566,8 @@ function checkEnvironmentData(data) { } function run_test() { + // Load a custom manifest to provide search engine loading from JAR files. + do_load_manifest("chrome.manifest"); do_test_pending(); spoofGfxAdapter(); do_get_profile(); @@ -936,6 +943,64 @@ add_task(function* test_changeThrottling() { TelemetryEnvironment.unregisterChangeListener("testWatchPrefs_throttling"); }); +add_task(function* test_defaultSearchEngine() { + // Check that no default engine is in the environment before the search service is + // initialized. + let data = TelemetryEnvironment.currentEnvironment; + checkEnvironmentData(data); + Assert.ok(!("defaultSearchEngine" in data.settings)); + + // Load the engines definitions from a custom JAR file: that's needed so that + // the search provider reports an engine identifier. + let defaultBranch = Services.prefs.getDefaultBranch(null); + defaultBranch.setCharPref("browser.search.jarURIs", "chrome://testsearchplugin/locale/searchplugins/"); + defaultBranch.setBoolPref("browser.search.loadFromJars", true); + + // Initialize the search service and disable geoip lookup, so we don't get unwanted + // network connections. + Preferences.set("browser.search.geoip.url", ""); + yield new Promise(resolve => Services.search.init(resolve)); + + // Our default engine from the JAR file has an identifier. Check if it is correctly + // reported. + data = TelemetryEnvironment.currentEnvironment; + checkEnvironmentData(data); + Assert.equal(data.settings.defaultSearchEngine, "telemetrySearchIdentifier"); + + // Remove all the search engines. + for (let engine of Services.search.getEngines()) { + Services.search.removeEngine(engine); + } + // The search service does not notify "engine-default" when removing a default engine. + // Manually force the notification. + // TODO: remove this when bug 1165341 is resolved. + Services.obs.notifyObservers(null, "browser-search-engine-modified", "engine-default"); + + // Then check that no default engine is reported if none is available. + data = TelemetryEnvironment.currentEnvironment; + checkEnvironmentData(data); + Assert.equal(data.settings.defaultSearchEngine, "NONE"); + + // Add a new search engine (this will have no engine identifier). + const SEARCH_ENGINE_ID = "telemetry_default"; + const SEARCH_ENGINE_URL = "http://www.example.org/?search={searchTerms}"; + Services.search.addEngineWithDetails(SEARCH_ENGINE_ID, "", null, "", "get", SEARCH_ENGINE_URL); + + // Set the clock in the future so our changes don't get throttled. + gNow = fakeNow(futureDate(gNow, 10 * MILLISECONDS_PER_MINUTE)); + // Register a new change listener and then wait for the search engine change to be notified. + let deferred = PromiseUtils.defer(); + TelemetryEnvironment.registerChangeListener("testWatch_SearchDefault", deferred.resolve); + Services.search.defaultEngine = Services.search.getEngineByName(SEARCH_ENGINE_ID); + yield deferred.promise; + + data = TelemetryEnvironment.currentEnvironment; + checkEnvironmentData(data); + + const EXPECTED_SEARCH_ENGINE = "other-" + SEARCH_ENGINE_ID; + Assert.equal(data.settings.defaultSearchEngine, EXPECTED_SEARCH_ENGINE); +}); + add_task(function*() { do_test_finished(); }); diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js index 152e8fd67433..c31d082a7de9 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetrySession.js @@ -1363,6 +1363,39 @@ add_task(function* test_abortedSession() { yield TelemetrySession.shutdown(); }); +add_task(function* test_abortedSession_Shutdown() { + if (gIsAndroid || gIsGonk) { + // We don't have the aborted session ping here. + return; + } + + const ABORTED_FILE = OS.Path.join(DATAREPORTING_PATH, ABORTED_PING_FILE_NAME); + + let schedulerTickCallback = null; + let now = fakeNow(2040, 1, 1, 0, 0, 0); + // Fake scheduler functions to control aborted-session flow in tests. + fakeSchedulerTimer(callback => schedulerTickCallback = callback, () => {}); + yield TelemetrySession.reset(); + + Assert.ok((yield OS.File.exists(DATAREPORTING_PATH)), + "Telemetry must create the aborted session directory when starting."); + + // Fake now again so that the scheduled aborted-session save takes place. + now = fakeNow(futureDate(now, ABORTED_SESSION_UPDATE_INTERVAL_MS)); + // The first aborted session checkpoint must take place right after the initialisation. + Assert.ok(!!schedulerTickCallback); + // Execute one scheduler tick. + yield schedulerTickCallback(); + // Check that the aborted session is due at the correct time. + Assert.ok((yield OS.File.exists(ABORTED_FILE)), "There must be an aborted session ping."); + + // Remove the aborted session file and then shut down to make sure exceptions (e.g file + // not found) do not compromise the shutdown. + yield OS.File.remove(ABORTED_FILE); + + yield TelemetrySession.shutdown(); +}); + add_task(function* test_abortedDailyCoalescing() { if (gIsAndroid || gIsGonk) { // We don't have the aborted session or the daily ping here. diff --git a/toolkit/components/telemetry/tests/unit/xpcshell.ini b/toolkit/components/telemetry/tests/unit/xpcshell.ini index d1d8f498c3fc..a104590209d8 100644 --- a/toolkit/components/telemetry/tests/unit/xpcshell.ini +++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini @@ -5,6 +5,8 @@ skip-if = toolkit == 'gonk' # The *.xpi files are only needed for test_TelemetryEnvironment.js, but # xpcshell fails to install tests if we move them under the test entry. support-files = + ../search/chrome.manifest + ../search/searchTest.jar dictionary.xpi experiment.xpi extension.xpi diff --git a/toolkit/devtools/server/actors/styles.js b/toolkit/devtools/server/actors/styles.js index 39a6da7aa2fa..6f24981867c8 100644 --- a/toolkit/devtools/server/actors/styles.js +++ b/toolkit/devtools/server/actors/styles.js @@ -851,7 +851,7 @@ var PageStyleActor = protocol.ActorClass({ if (rawNode.id) { selector = "#" + rawNode.id; } else if (rawNode.className) { - selector = "." + rawNode.className.split(" ")[0]; + selector = "." + rawNode.className.split(" ").join("."); } else { selector = rawNode.tagName.toLowerCase(); }