From 43d54ab19e5f82d5d019a289f502bc90f978ae64 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Fri, 8 Jan 2016 20:25:27 -0800 Subject: [PATCH] Back out 8 changesets (bug 1235345, bug 1234526, bug 1234522, bug 1237700) for OS X 10.10 debug xpcshell timeouts in test_ocsp_stapling.js and test_ocsp_stapling_expired.js CLOSED TREE Backed out changeset f26c050a39a1 (bug 1235345) Backed out changeset c7689b72d3fa (bug 1234526) Backed out changeset 3124025d1147 (bug 1234526) Backed out changeset 096d46bdaf86 (bug 1234526) Backed out changeset 96e0326e7985 (bug 1234522) Backed out changeset c3b6bf176f86 (bug 1234522) Backed out changeset 3e7dc6d87325 (bug 1234522) Backed out changeset f6447d37d113 (bug 1237700) --- b2g/confvars.sh | 1 + b2g/graphene/confvars.sh | 1 + b2g/installer/package-manifest.in | 4 + .../content/abouthealthreport/abouthealth.js | 16 + .../browser-data-submission-info-bar.js | 5 +- browser/base/content/browser.js | 64 +- browser/base/content/test/general/browser.ini | 3 + .../test/general/browser_aboutHealthReport.js | 297 +-- .../content/test/general/browser_aboutHome.js | 46 +- .../browser_contextSearchTabPosition.js | 78 +- .../browser_datachoices_notification.js | 16 + .../browser_datareporting_notification.js | 213 ++ .../general/browser_urlbarSearchTelemetry.js | 5 + .../browser_urlbar_search_healthreport.js | 85 + browser/base/content/test/general/head.js | 58 + .../healthreport_testRemoteCommands.html | 41 +- browser/base/content/urlbarBindings.xml | 2 +- browser/components/nsBrowserGlue.js | 2 +- .../preferences/in-content/advanced.js | 25 +- .../preferences/in-content/tests/browser.ini | 2 +- .../in-content/tests/browser_healthreport.js | 32 +- browser/components/search/content/search.xml | 2 +- .../search/test/browser_healthreport.js | 104 +- .../selfsupport/SelfSupportService.js | 50 + browser/confvars.sh | 1 + browser/experiments/ExperimentsService.js | 4 +- browser/installer/package-manifest.in | 5 + browser/modules/ContentSearch.jsm | 4 +- browser/modules/SelfSupportBackend.jsm | 6 +- dom/webidl/MozSelfSupport.webidl | 20 + embedding/ios/confvars.sh | 1 + .../b2gdroid/installer/package-manifest.in | 5 + modules/libpref/greprefs.js | 4 +- services/datareporting/DataReporting.manifest | 16 + .../datareporting/DataReportingService.js | 296 +++ .../datareporting}/datareporting-prefs.js | 2 + .../datareporting/modules-testing/mocks.jsm | 52 + services/datareporting/moz.build | 23 + services/datareporting/policy.jsm | 927 +++++++ services/datareporting/tests/xpcshell/head.js | 16 + .../tests/xpcshell/test_policy.js | 689 ++++++ .../datareporting/tests/xpcshell/xpcshell.ini | 6 + services/docs/datareporting.rst | 28 + services/docs/index.rst | 17 + services/docs/metrics.rst | 130 + services/healthreport/HealthReport.jsm | 43 + .../HealthReportComponents.manifest | 16 + .../healthreport/docs}/architecture.rst | 0 .../healthreport/docs}/dataformat.rst | 0 .../healthreport/docs}/identifiers.rst | 0 .../healthreport/docs}/index.rst | 10 +- services/healthreport/healthreport-prefs.js | 38 + services/healthreport/healthreporter.jsm | 1507 ++++++++++++ .../healthreport/modules-testing/utils.jsm | 219 ++ services/healthreport/moz.build | 27 + services/healthreport/profile.jsm | 124 + services/healthreport/providers.jsm | 1792 ++++++++++++++ services/healthreport/tests/xpcshell/head.js | 21 + .../tests/xpcshell/test_healthreporter.js | 1284 ++++++++++ .../tests/xpcshell/test_load_modules.js | 20 + .../tests/xpcshell/test_profile.js | 258 ++ .../tests/xpcshell/test_provider_addons.js | 339 +++ .../tests/xpcshell/test_provider_appinfo.js | 281 +++ .../tests/xpcshell/test_provider_crashes.js | 137 ++ .../tests/xpcshell/test_provider_hotfix.js | 179 ++ .../tests/xpcshell/test_provider_places.js | 46 + .../tests/xpcshell/test_provider_searches.js | 187 ++ .../tests/xpcshell/test_provider_sessions.js | 217 ++ .../tests/xpcshell/test_provider_sysinfo.js | 41 + .../healthreport/tests/xpcshell/xpcshell.ini | 20 + services/metrics/Metrics.jsm | 38 + services/metrics/dataprovider.jsm | 727 ++++++ services/metrics/modules-testing/mocks.jsm | 154 ++ services/metrics/moz.build | 23 + services/metrics/providermanager.jsm | 558 +++++ services/metrics/storage.jsm | 2186 +++++++++++++++++ services/metrics/tests/xpcshell/head.js | 15 + .../tests/xpcshell/test_load_modules.js | 31 + .../tests/xpcshell/test_metrics_provider.js | 297 +++ .../xpcshell/test_metrics_provider_manager.js | 357 +++ .../tests/xpcshell/test_metrics_storage.js | 839 +++++++ services/metrics/tests/xpcshell/xpcshell.ini | 9 + services/moz.build | 14 + .../driver/marionette_driver/geckoinstance.py | 3 + toolkit/components/telemetry/Telemetry.cpp | 1 + .../telemetry/TelemetryController.jsm | 16 +- .../components/telemetry/TelemetrySession.jsm | 3 + .../telemetry/healthreport-prefs.js | 12 - toolkit/components/telemetry/moz.build | 1 - .../components/telemetry/tests/unit/head.js | 2 + .../tests/unit/test_TelemetryController.js | 14 +- .../unit/test_TelemetryControllerBuildID.js | 12 + .../unit/test_TelemetryControllerShutdown.js | 10 + .../unit/test_TelemetryReportingPolicy.js | 3 + .../tests/unit/test_TelemetrySendOldPings.js | 10 + .../tests/unit/test_TelemetrySession.js | 1 + .../tests/unit/test_TelemetryTimestamps.js | 12 + toolkit/modules/SessionRecorder.jsm | 5 +- xulrunner/confvars.sh | 1 + 99 files changed, 15236 insertions(+), 328 deletions(-) create mode 100644 browser/base/content/test/general/browser_datareporting_notification.js create mode 100644 browser/base/content/test/general/browser_urlbar_search_healthreport.js create mode 100644 services/datareporting/DataReporting.manifest create mode 100644 services/datareporting/DataReportingService.js rename {toolkit/components/telemetry => services/datareporting}/datareporting-prefs.js (85%) create mode 100644 services/datareporting/modules-testing/mocks.jsm create mode 100644 services/datareporting/moz.build create mode 100644 services/datareporting/policy.jsm create mode 100644 services/datareporting/tests/xpcshell/head.js create mode 100644 services/datareporting/tests/xpcshell/test_policy.js create mode 100644 services/datareporting/tests/xpcshell/xpcshell.ini create mode 100644 services/docs/datareporting.rst create mode 100644 services/docs/index.rst create mode 100644 services/docs/metrics.rst create mode 100644 services/healthreport/HealthReport.jsm create mode 100644 services/healthreport/HealthReportComponents.manifest rename {toolkit/components/telemetry/docs/fhr => services/healthreport/docs}/architecture.rst (100%) rename {toolkit/components/telemetry/docs/fhr => services/healthreport/docs}/dataformat.rst (100%) rename {toolkit/components/telemetry/docs/fhr => services/healthreport/docs}/identifiers.rst (100%) rename {toolkit/components/telemetry/docs/fhr => services/healthreport/docs}/index.rst (81%) create mode 100644 services/healthreport/healthreport-prefs.js create mode 100644 services/healthreport/healthreporter.jsm create mode 100644 services/healthreport/modules-testing/utils.jsm create mode 100644 services/healthreport/moz.build create mode 100644 services/healthreport/profile.jsm create mode 100644 services/healthreport/providers.jsm create mode 100644 services/healthreport/tests/xpcshell/head.js create mode 100644 services/healthreport/tests/xpcshell/test_healthreporter.js create mode 100644 services/healthreport/tests/xpcshell/test_load_modules.js create mode 100644 services/healthreport/tests/xpcshell/test_profile.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_addons.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_appinfo.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_crashes.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_hotfix.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_places.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_searches.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_sessions.js create mode 100644 services/healthreport/tests/xpcshell/test_provider_sysinfo.js create mode 100644 services/healthreport/tests/xpcshell/xpcshell.ini create mode 100644 services/metrics/Metrics.jsm create mode 100644 services/metrics/dataprovider.jsm create mode 100644 services/metrics/modules-testing/mocks.jsm create mode 100644 services/metrics/moz.build create mode 100644 services/metrics/providermanager.jsm create mode 100644 services/metrics/storage.jsm create mode 100644 services/metrics/tests/xpcshell/head.js create mode 100644 services/metrics/tests/xpcshell/test_load_modules.js create mode 100644 services/metrics/tests/xpcshell/test_metrics_provider.js create mode 100644 services/metrics/tests/xpcshell/test_metrics_provider_manager.js create mode 100644 services/metrics/tests/xpcshell/test_metrics_storage.js create mode 100644 services/metrics/tests/xpcshell/xpcshell.ini delete mode 100644 toolkit/components/telemetry/healthreport-prefs.js diff --git a/b2g/confvars.sh b/b2g/confvars.sh index 1e94ada62ce..bbdf616047d 100644 --- a/b2g/confvars.sh +++ b/b2g/confvars.sh @@ -19,6 +19,7 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official MOZ_SAFE_BROWSING=1 MOZ_SERVICES_COMMON=1 +MOZ_SERVICES_METRICS=1 MOZ_WEBSMS_BACKEND=1 MOZ_NO_SMART_CARDS=1 diff --git a/b2g/graphene/confvars.sh b/b2g/graphene/confvars.sh index 4db1b760931..8a557d3c03b 100644 --- a/b2g/graphene/confvars.sh +++ b/b2g/graphene/confvars.sh @@ -26,6 +26,7 @@ MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official MOZ_SAFE_BROWSING=1 MOZ_SERVICES_COMMON=1 +MOZ_SERVICES_METRICS=1 MOZ_CAPTIVEDETECT=1 MOZ_WEBSMS_BACKEND=1 diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index eb8215384c3..11a3dc5072f 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -631,6 +631,10 @@ #endif @RESPATH@/components/servicesComponents.manifest @RESPATH@/components/cryptoComponents.manifest +#ifdef MOZ_SERVICES_HEALTHREPORT +@RESPATH@/components/HealthReportComponents.manifest +@RESPATH@/components/HealthReportService.js +#endif @RESPATH@/components/CaptivePortalDetectComponents.manifest @RESPATH@/components/captivedetect.js @RESPATH@/components/TelemetryStartup.js diff --git a/browser/base/content/abouthealthreport/abouthealth.js b/browser/base/content/abouthealthreport/abouthealth.js index f90f6742d5d..55669edc473 100644 --- a/browser/base/content/abouthealthreport/abouthealth.js +++ b/browser/base/content/abouthealthreport/abouthealth.js @@ -23,6 +23,10 @@ var healthReportWrapper = { let iframe = document.getElementById("remote-report"); iframe.addEventListener("load", healthReportWrapper.initRemotePage, false); iframe.src = this._getReportURI().spec; + iframe.onload = () => { + MozSelfSupport.getHealthReportPayload().then(this.updatePayload, + this.handleInitFailure); + }; prefs.observe("uploadEnabled", this.updatePrefState, healthReportWrapper); }, @@ -99,6 +103,15 @@ var healthReportWrapper = { }); }, + refreshPayload: function () { + MozSelfSupport.getHealthReportPayload().then(this.updatePayload, + this.handlePayloadFailure); + }, + + updatePayload: function (payload) { + healthReportWrapper.injectData("payload", JSON.stringify(payload)); + }, + injectData: function (type, content) { let report = this._getReportURI(); @@ -126,6 +139,9 @@ var healthReportWrapper = { case "RequestCurrentPrefs": this.updatePrefState(); break; + case "RequestCurrentPayload": + this.refreshPayload(); + break; case "RequestTelemetryPingList": this.sendTelemetryPingList(); break; diff --git a/browser/base/content/browser-data-submission-info-bar.js b/browser/base/content/browser-data-submission-info-bar.js index cd7cddd9e46..93f79d092d5 100644 --- a/browser/base/content/browser-data-submission-info-bar.js +++ b/browser/base/content/browser-data-submission-info-bar.js @@ -2,9 +2,6 @@ * 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/. */ -const LOGGER_NAME = "Toolkit.Telemetry"; -const LOGGER_PREFIX = "DataNotificationInfoBar::"; - /** * Represents an info bar that shows a data submission notification. */ @@ -24,7 +21,7 @@ var gDataNotificationInfoBar = { get _log() { let Log = Cu.import("resource://gre/modules/Log.jsm", {}).Log; delete this._log; - return this._log = Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, LOGGER_PREFIX); + return this._log = Log.repository.getLogger("Services.DataReporting.InfoBar"); }, init: function() { diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 1f097bd4b09..f8469accfe7 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -3633,7 +3633,7 @@ const BrowserSearch = { loadSearchFromContext: function (terms) { let engine = BrowserSearch._loadSearch(terms, true, "contextmenu"); if (engine) { - BrowserSearch.recordSearchInTelemetry(engine, "contextmenu"); + BrowserSearch.recordSearchInHealthReport(engine, "contextmenu"); } }, @@ -3657,26 +3657,10 @@ const BrowserSearch = { openUILinkIn(searchEnginesURL, where); }, - _getSearchEngineId: function (engine) { - if (!engine) { - return "other"; - } - - if (engine.identifier) { - return engine.identifier; - } - - if (!("name" in engine) || engine.name === undefined) { - return "other"; - } - - return "other-" + engine.name; - }, - /** - * Helper to record a search with Telemetry. + * Helper to record a search with Firefox Health Report. * - * Telemetry records only search counts and nothing pertaining to the search itself. + * FHR records only search counts and nothing pertaining to the search itself. * * @param engine * (nsISearchEngine) The engine handling the search. @@ -3688,7 +3672,45 @@ const BrowserSearch = { * the search was a suggested search, this indicates where the * item was in the suggestion list and how the user selected it. */ - recordSearchInTelemetry: function (engine, source, selection) { + recordSearchInHealthReport: function (engine, source, selection) { + BrowserUITelemetry.countSearchEvent(source, null, selection); + this.recordSearchInTelemetry(engine, source); + + let reporter = AppConstants.MOZ_SERVICES_HEALTHREPORT + ? Cc["@mozilla.org/datareporting/service;1"] + .getService() + .wrappedJSObject + .healthReporter + : null; + + // This can happen if the FHR component of the data reporting service is + // disabled. This is controlled by a pref that most will never use. + if (!reporter) { + return; + } + + reporter.onInit().then(function record() { + try { + reporter.getProvider("org.mozilla.searches").recordSearch(engine, source); + } catch (ex) { + Cu.reportError(ex); + } + }); + }, + + _getSearchEngineId: function (engine) { + if (!engine) { + return "other"; + } + + if (engine.identifier) { + return engine.identifier; + } + + return "other-" + engine.name; + }, + + recordSearchInTelemetry: function (engine, source) { const SOURCES = [ "abouthome", "contextmenu", @@ -3697,8 +3719,6 @@ const BrowserSearch = { "urlbar", ]; - BrowserUITelemetry.countSearchEvent(source, null, selection); - if (SOURCES.indexOf(source) == -1) { Cu.reportError("Unknown source for search: " + source); return; diff --git a/browser/base/content/test/general/browser.ini b/browser/base/content/test/general/browser.ini index 5c75c85458d..3723d391d20 100644 --- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -286,6 +286,8 @@ skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only [browser_contextSearchTabPosition.js] skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash [browser_ctrlTab.js] +[browser_datareporting_notification.js] +skip-if = !datareporting [browser_datachoices_notification.js] skip-if = !datareporting [browser_devedition.js] @@ -478,6 +480,7 @@ skip-if = os == "linux" # Bug 1073339 - Investigate autocomplete test unreliabil [browser_urlbarStop.js] [browser_urlbarTrimURLs.js] [browser_urlbar_autoFill_backspaced.js] +[browser_urlbar_search_healthreport.js] [browser_urlbar_searchsettings.js] [browser_utilityOverlay.js] [browser_viewSourceInTabOnViewSource.js] diff --git a/browser/base/content/test/general/browser_aboutHealthReport.js b/browser/base/content/test/general/browser_aboutHealthReport.js index 33d1a1c5840..d22497fc2cd 100644 --- a/browser/base/content/test/general/browser_aboutHealthReport.js +++ b/browser/base/content/test/general/browser_aboutHealthReport.js @@ -1,143 +1,154 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -const CHROME_BASE = "chrome://mochitests/content/browser/browser/base/content/test/general/"; -const HTTPS_BASE = "https://example.com/browser/browser/base/content/test/general/"; - -const TELEMETRY_LOG_PREF = "toolkit.telemetry.log.level"; -const telemetryOriginalLogPref = Preferences.get(TELEMETRY_LOG_PREF, null); - -const originalReportUrl = Services.prefs.getCharPref("datareporting.healthreport.about.reportUrl"); -const originalReportUrlUnified = Services.prefs.getCharPref("datareporting.healthreport.about.reportUrlUnified"); - -registerCleanupFunction(function() { - // Ensure we don't pollute prefs for next tests. - if (telemetryOriginalLogPref) { - Preferences.set(TELEMETRY_LOG_PREF, telemetryOriginalLogPref); - } else { - Preferences.reset(TELEMETRY_LOG_PREF); - } - - try { - Services.prefs.setCharPref("datareporting.healthreport.about.reportUrl", originalReportUrl); - Services.prefs.setCharPref("datareporting.healthreport.about.reportUrlUnified", originalReportUrlUnified); - Services.prefs.setBoolPref("datareporting.healthreport.uploadEnabled", true); - } catch (ex) {} -}); - -function fakeTelemetryNow(...args) { - let date = new Date(...args); - let scope = {}; - const modules = [ - Cu.import("resource://gre/modules/TelemetrySession.jsm", scope), - Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", scope), - Cu.import("resource://gre/modules/TelemetryController.jsm", scope), - ]; - - for (let m of modules) { - m.Policy.now = () => new Date(date); - } - - return date; -} - -function setupPingArchive() { - let scope = {}; - Cu.import("resource://gre/modules/TelemetryController.jsm", scope); - Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader) - .loadSubScript(CHROME_BASE + "healthreport_pingData.js", scope); - - for (let p of scope.TEST_PINGS) { - fakeTelemetryNow(p.date); - p.id = yield scope.TelemetryController.submitExternalPing(p.type, p.payload); - } -} - -var gTests = [ - -{ - desc: "Test the remote commands", - setup: Task.async(function*() - { - Preferences.set(TELEMETRY_LOG_PREF, "Trace"); - yield setupPingArchive(); - Preferences.set("datareporting.healthreport.about.reportUrl", - HTTPS_BASE + "healthreport_testRemoteCommands.html"); - Preferences.set("datareporting.healthreport.about.reportUrlUnified", - HTTPS_BASE + "healthreport_testRemoteCommands.html"); - }), - run: function (iframe) - { - let deferred = Promise.defer(); - let results = 0; - try { - iframe.contentWindow.addEventListener("FirefoxHealthReportTestResponse", function evtHandler(event) { - let data = event.detail.data; - if (data.type == "testResult") { - ok(data.pass, data.info); - results++; - } - else if (data.type == "testsComplete") { - is(results, data.count, "Checking number of results received matches the number of tests that should have run"); - iframe.contentWindow.removeEventListener("FirefoxHealthReportTestResponse", evtHandler, true); - deferred.resolve(); - } - }, true); - - } catch(e) { - ok(false, "Failed to get all commands"); - deferred.reject(); - } - return deferred.promise; - } -}, - -]; // gTests - -function test() -{ - waitForExplicitFinish(); - - // xxxmpc leaving this here until we resolve bug 854038 and bug 854060 - requestLongerTimeout(10); - - Task.spawn(function () { - for (let test of gTests) { - info(test.desc); - yield test.setup(); - - let iframe = yield promiseNewTabLoadEvent("about:healthreport"); - - yield test.run(iframe); - - gBrowser.removeCurrentTab(); - } - - finish(); - }); -} - -function promiseNewTabLoadEvent(aUrl, aEventType="load") -{ - let deferred = Promise.defer(); - let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); - tab.linkedBrowser.addEventListener(aEventType, function load(event) { - tab.linkedBrowser.removeEventListener(aEventType, load, true); - let iframe = tab.linkedBrowser.contentDocument.getElementById("remote-report"); - iframe.addEventListener("load", function frameLoad(e) { - if (iframe.contentWindow.location.href == "about:blank" || - e.target != iframe) { - return; - } - iframe.removeEventListener("load", frameLoad, false); - deferred.resolve(iframe); - }, false); - }, true); - return deferred.promise; -} +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/Promise.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + +const CHROME_BASE = "chrome://mochitests/content/browser/browser/base/content/test/general/"; +const HTTPS_BASE = "https://example.com/browser/browser/base/content/test/general/"; + +const TELEMETRY_LOG_PREF = "toolkit.telemetry.log.level"; +const telemetryOriginalLogPref = Preferences.get(TELEMETRY_LOG_PREF, null); + +const originalReportUrl = Services.prefs.getCharPref("datareporting.healthreport.about.reportUrl"); +const originalReportUrlUnified = Services.prefs.getCharPref("datareporting.healthreport.about.reportUrlUnified"); + +registerCleanupFunction(function() { + // Ensure we don't pollute prefs for next tests. + if (telemetryOriginalLogPref) { + Preferences.set(TELEMETRY_LOG_PREF, telemetryOriginalLogPref); + } else { + Preferences.reset(TELEMETRY_LOG_PREF); + } + + try { + Services.prefs.setCharPref("datareporting.healthreport.about.reportUrl", originalReportUrl); + Services.prefs.setCharPref("datareporting.healthreport.about.reportUrlUnified", originalReportUrlUnified); + let policy = Cc["@mozilla.org/datareporting/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject + .policy; + policy.recordHealthReportUploadEnabled(true, + "Resetting after tests."); + } catch (ex) {} +}); + +function fakeTelemetryNow(...args) { + let date = new Date(...args); + let scope = {}; + const modules = [ + Cu.import("resource://gre/modules/TelemetrySession.jsm", scope), + Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", scope), + Cu.import("resource://gre/modules/TelemetryController.jsm", scope), + ]; + + for (let m of modules) { + m.Policy.now = () => new Date(date); + } + + return date; +} + +function setupPingArchive() { + let scope = {}; + Cu.import("resource://gre/modules/TelemetryController.jsm", scope); + Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader) + .loadSubScript(CHROME_BASE + "healthreport_pingData.js", scope); + + for (let p of scope.TEST_PINGS) { + fakeTelemetryNow(p.date); + p.id = yield scope.TelemetryController.submitExternalPing(p.type, p.payload); + } +} + +var gTests = [ + +{ + desc: "Test the remote commands", + setup: Task.async(function*() + { + Preferences.set(TELEMETRY_LOG_PREF, "Trace"); + yield setupPingArchive(); + Preferences.set("datareporting.healthreport.about.reportUrl", + HTTPS_BASE + "healthreport_testRemoteCommands.html"); + Preferences.set("datareporting.healthreport.about.reportUrlUnified", + HTTPS_BASE + "healthreport_testRemoteCommands.html"); + }), + run: function (iframe) + { + let deferred = Promise.defer(); + + let policy = Cc["@mozilla.org/datareporting/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject + .policy; + + let results = 0; + try { + iframe.contentWindow.addEventListener("FirefoxHealthReportTestResponse", function evtHandler(event) { + let data = event.detail.data; + if (data.type == "testResult") { + ok(data.pass, data.info); + results++; + } + else if (data.type == "testsComplete") { + is(results, data.count, "Checking number of results received matches the number of tests that should have run"); + iframe.contentWindow.removeEventListener("FirefoxHealthReportTestResponse", evtHandler, true); + deferred.resolve(); + } + }, true); + + } catch(e) { + ok(false, "Failed to get all commands"); + deferred.reject(); + } + return deferred.promise; + } +}, + +]; // gTests + +function test() +{ + waitForExplicitFinish(); + + // xxxmpc leaving this here until we resolve bug 854038 and bug 854060 + requestLongerTimeout(10); + + Task.spawn(function () { + for (let test of gTests) { + info(test.desc); + yield test.setup(); + + let iframe = yield promiseNewTabLoadEvent("about:healthreport"); + + yield test.run(iframe); + + gBrowser.removeCurrentTab(); + } + + finish(); + }); +} + +function promiseNewTabLoadEvent(aUrl, aEventType="load") +{ + let deferred = Promise.defer(); + let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); + tab.linkedBrowser.addEventListener(aEventType, function load(event) { + tab.linkedBrowser.removeEventListener(aEventType, load, true); + let iframe = tab.linkedBrowser.contentDocument.getElementById("remote-report"); + iframe.addEventListener("load", function frameLoad(e) { + if (iframe.contentWindow.location.href == "about:blank" || + e.target != iframe) { + return; + } + iframe.removeEventListener("load", frameLoad, false); + deferred.resolve(iframe); + }, false); + }, true); + return deferred.promise; +} diff --git a/browser/base/content/test/general/browser_aboutHome.js b/browser/base/content/test/general/browser_aboutHome.js index 74696e0cdc3..c32eb95ebd7 100644 --- a/browser/base/content/test/general/browser_aboutHome.js +++ b/browser/base/content/test/general/browser_aboutHome.js @@ -78,11 +78,24 @@ var gTests = [ } }, +// Disabled on Linux for intermittent issues with FHR, see Bug 945667. { desc: "Check that performing a search fires a search event and records to " + - "Telemetry.", + "Firefox Health Report.", setup: function () { }, run: function* () { + // Skip this test on Linux. + if (navigator.platform.indexOf("Linux") == 0) { + return Promise.resolve(); + } + + try { + let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); + cm.getCategoryEntry("healthreport-js-provider-default", "SearchesProvider"); + } catch (ex) { + // Health Report disabled, or no SearchesProvider. + return Promise.resolve(); + } let engine = yield promiseNewEngine("searchSuggestionEngine.xml"); // Make this actually work in healthreport by giving it an ID: @@ -100,32 +113,23 @@ var gTests = [ is(engine.name, engineName, "Engine name in DOM should match engine we just added"); // Get the current number of recorded searches. - let histogramKey = engine.identifier + ".abouthome"; - try { - let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot(); - if (histogramKey in hs) { - numSearchesBefore = hs[histogramKey].sum; - } - } catch (ex) { - // No searches performed yet, not a problem, |numSearchesBefore| is 0. - } - - // Perform a search to increase the SEARCH_COUNT histogram. let searchStr = "a search"; - info("Perform a search."); - doc.getElementById("searchText").value = searchStr; - doc.getElementById("searchSubmit").click(); + getNumberOfSearchesInFHR(engineName, "abouthome").then(num => { + numSearchesBefore = num; + + info("Perform a search."); + doc.getElementById("searchText").value = searchStr; + doc.getElementById("searchSubmit").click(); + }); let expectedURL = Services.search.currentEngine. getSubmission(searchStr, null, "homepage"). uri.spec; let loadPromise = waitForDocLoadAndStopIt(expectedURL).then(() => { - // Make sure the SEARCH_COUNTS histogram has the right key and count. - let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot(); - Assert.ok(histogramKey in hs, "histogram with key should be recorded"); - Assert.equal(hs[histogramKey].sum, numSearchesBefore + 1, - "histogram sum should be incremented"); - searchEventDeferred.resolve(); + getNumberOfSearchesInFHR(engineName, "abouthome").then(num => { + is(num, numSearchesBefore + 1, "One more search recorded."); + searchEventDeferred.resolve(); + }); }); try { diff --git a/browser/base/content/test/general/browser_contextSearchTabPosition.js b/browser/base/content/test/general/browser_contextSearchTabPosition.js index 76646789000..b8ac3c04356 100644 --- a/browser/base/content/test/general/browser_contextSearchTabPosition.js +++ b/browser/base/content/test/general/browser_contextSearchTabPosition.js @@ -2,35 +2,16 @@ * 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/. */ -add_task(function* test() { - - // Will need to be changed if Google isn't the default search engine. - // Note: geoSpecificDefaults are disabled for mochitests, so this is the - // non-US en-US default. - let histogramKey = "google.contextmenu"; - let numSearchesBefore = 0; - try { - let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot(); - if (histogramKey in hs) { - numSearchesBefore = hs[histogramKey].sum; - } - } catch (ex) { - // No searches performed yet, not a problem, |numSearchesBefore| is 0. - } - - let tabs = []; - let tabsLoadedDeferred = Promise.defer(); +function test() { + waitForExplicitFinish(); function tabAdded(event) { let tab = event.target; tabs.push(tab); - - // We wait for the blank tab and the two context searches tabs to open. - if (tabs.length == 3) { - tabsLoadedDeferred.resolve(); - } } + let tabs = []; + let container = gBrowser.tabContainer; container.addEventListener("TabOpen", tabAdded, false); @@ -38,9 +19,6 @@ add_task(function* test() { BrowserSearch.loadSearchFromContext("mozilla"); BrowserSearch.loadSearchFromContext("firefox"); - // Wait for all the tabs to open. - yield tabsLoadedDeferred.promise; - is(tabs[0], gBrowser.tabs[3], "blank tab has been pushed to the end"); is(tabs[1], gBrowser.tabs[1], "first search tab opens next to the current tab"); is(tabs[2], gBrowser.tabs[2], "second search tab opens next to the first search tab"); @@ -48,9 +26,45 @@ add_task(function* test() { container.removeEventListener("TabOpen", tabAdded, false); tabs.forEach(gBrowser.removeTab, gBrowser); - // Make sure that the context searches are correctly recorded. - let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot(); - Assert.ok(histogramKey in hs, "The histogram must contain the correct key"); - Assert.equal(hs[histogramKey].sum, numSearchesBefore + 2, - "The histogram must contain the correct search count"); -}); + try { + let cm = Components.classes["@mozilla.org/categorymanager;1"] + .getService(Components.interfaces.nsICategoryManager); + cm.getCategoryEntry("healthreport-js-provider-default", "SearchesProvider"); + } catch (ex) { + // Health Report disabled, or no SearchesProvider. + finish(); + return; + } + + let reporter = Components.classes["@mozilla.org/datareporting/service;1"] + .getService() + .wrappedJSObject + .healthReporter; + + // reporter should always be available in automation. + ok(reporter, "Health Reporter available."); + reporter.onInit().then(function onInit() { + let provider = reporter.getProvider("org.mozilla.searches"); + ok(provider, "Searches provider is available."); + + let m = provider.getMeasurement("counts", 3); + m.getValues().then(function onValues(data) { + let now = new Date(); + ok(data.days.hasDay(now), "Have data for today."); + let day = data.days.getDay(now); + + // Will need to be changed if Google isn't the default search engine. + // Note: geoSpecificDefaults are disabled for mochitests, so this is the + // non-US en-US default. + let defaultProviderID = "google"; + let field = defaultProviderID + ".contextmenu"; + ok(day.has(field), "Have search recorded for context menu."); + + // If any other mochitests perform a context menu search, this will fail. + // The solution will be to look up count at test start and ensure it is + // incremented by two. + is(day.get(field), 2, "2 searches recorded in FHR."); + finish(); + }); + }); +} diff --git a/browser/base/content/test/general/browser_datachoices_notification.js b/browser/base/content/test/general/browser_datachoices_notification.js index 17fa14ea860..729a29e3f12 100644 --- a/browser/base/content/test/general/browser_datachoices_notification.js +++ b/browser/base/content/test/general/browser_datachoices_notification.js @@ -10,7 +10,13 @@ var Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Prefer var TelemetryReportingPolicy = Cu.import("resource://gre/modules/TelemetryReportingPolicy.jsm", {}).TelemetryReportingPolicy; +XPCOMUtils.defineLazyGetter(this, "gDatareportingService", + () => Cc["@mozilla.org/datareporting/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject); + const PREF_BRANCH = "datareporting.policy."; +const PREF_DRS_ENABLED = "datareporting.healthreport.service.enabled"; const PREF_BYPASS_NOTIFICATION = PREF_BRANCH + "dataSubmissionPolicyBypassNotification"; const PREF_CURRENT_POLICY_VERSION = PREF_BRANCH + "currentPolicyVersion"; const PREF_ACCEPTED_POLICY_VERSION = PREF_BRANCH + "dataSubmissionPolicyAcceptedVersion"; @@ -97,21 +103,31 @@ var checkInfobarButton = Task.async(function* (aNotification) { }); add_task(function* setup(){ + const drsEnabled = Preferences.get(PREF_DRS_ENABLED, true); const bypassNotification = Preferences.get(PREF_BYPASS_NOTIFICATION, true); const currentPolicyVersion = Preferences.get(PREF_CURRENT_POLICY_VERSION, 1); // Register a cleanup function to reset our preferences. registerCleanupFunction(() => { + Preferences.set(PREF_DRS_ENABLED, drsEnabled); Preferences.set(PREF_BYPASS_NOTIFICATION, bypassNotification); Preferences.set(PREF_CURRENT_POLICY_VERSION, currentPolicyVersion); + // Start polling again. + gDatareportingService.policy.startPolling(); + return closeAllNotifications(); }); + // Disable Healthreport/Data reporting service. + Preferences.set(PREF_DRS_ENABLED, false); // Don't skip the infobar visualisation. Preferences.set(PREF_BYPASS_NOTIFICATION, false); // Set the current policy version. Preferences.set(PREF_CURRENT_POLICY_VERSION, TEST_POLICY_VERSION); + + // Stop the polling to make sure no policy gets displayed by FHR. + gDatareportingService.policy.stopPolling(); }); function clearAcceptedPolicy() { diff --git a/browser/base/content/test/general/browser_datareporting_notification.js b/browser/base/content/test/general/browser_datareporting_notification.js new file mode 100644 index 00000000000..ce18a5f5a0d --- /dev/null +++ b/browser/base/content/test/general/browser_datareporting_notification.js @@ -0,0 +1,213 @@ +/* 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/. */ + +var originalPolicy = null; + +/** + * Display a datareporting notification to the user. + * + * @param {String} name + */ +function sendNotifyRequest(name) { + let ns = {}; + Cu.import("resource://gre/modules/services/datareporting/policy.jsm", ns); + Cu.import("resource://gre/modules/Preferences.jsm", ns); + + let service = Cc["@mozilla.org/datareporting/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject; + ok(service.healthReporter, "Health Reporter instance is available."); + + Cu.import("resource://gre/modules/Promise.jsm", ns); + let deferred = ns.Promise.defer(); + + if (!originalPolicy) { + originalPolicy = service.policy; + } + + let policyPrefs = new ns.Preferences("testing." + name + "."); + ok(service._prefs, "Health Reporter prefs are available."); + let hrPrefs = service._prefs; + + let policy = new ns.DataReportingPolicy(policyPrefs, hrPrefs, service); + policy.dataSubmissionPolicyBypassNotification = false; + service.policy = policy; + policy.firstRunDate = new Date(Date.now() - 24 * 60 * 60 * 1000); + + service.healthReporter.onInit().then(function onSuccess () { + is(policy.ensureUserNotified(), false, "User not notified about data policy on init."); + ok(policy._userNotifyPromise, "_userNotifyPromise defined."); + policy._userNotifyPromise.then( + deferred.resolve.bind(deferred), + deferred.reject.bind(deferred) + ); + }.bind(this), deferred.reject.bind(deferred)); + + return [policy, deferred.promise]; +} + +var dumpAppender, rootLogger; + +function test() { + registerCleanupFunction(cleanup); + waitForExplicitFinish(); + + let ns = {}; + Components.utils.import("resource://gre/modules/Log.jsm", ns); + rootLogger = ns.Log.repository.rootLogger; + dumpAppender = new ns.Log.DumpAppender(); + dumpAppender.level = ns.Log.Level.All; + rootLogger.addAppender(dumpAppender); + + closeAllNotifications().then(function onSuccess () { + let notification = document.getElementById("global-notificationbox"); + + notification.addEventListener("AlertActive", function active() { + notification.removeEventListener("AlertActive", active, true); + is(notification.allNotifications.length, 1, "Notification Displayed."); + + executeSoon(function afterNotification() { + waitForNotificationClose(notification.currentNotification, function onClose() { + is(notification.allNotifications.length, 0, "No notifications remain."); + is(policy.dataSubmissionPolicyAcceptedVersion, 1, "Version pref set."); + ok(policy.dataSubmissionPolicyNotifiedDate.getTime() > -1, "Date pref set."); + test_multiple_windows(); + }); + notification.currentNotification.close(); + }); + }, true); + + let [policy, promise] = sendNotifyRequest("single_window_notified"); + + is(policy.dataSubmissionPolicyAcceptedVersion, 0, "No version should be set on init."); + is(policy.dataSubmissionPolicyNotifiedDate.getTime(), 0, "No date should be set on init."); + is(policy.userNotifiedOfCurrentPolicy, false, "User not notified about datareporting policy."); + + promise.then(function () { + is(policy.dataSubmissionPolicyAcceptedVersion, 1, "Policy version set."); + is(policy.dataSubmissionPolicyNotifiedDate.getTime() > 0, true, "Policy date set."); + is(policy.userNotifiedOfCurrentPolicy, true, "User notified about datareporting policy."); + }.bind(this), function (err) { + throw err; + }); + + }.bind(this), function onError (err) { + throw err; + }); +} + +function test_multiple_windows() { + // Ensure we see the notification on all windows and that action on one window + // results in dismiss on every window. + let window2 = OpenBrowserWindow(); + whenDelayedStartupFinished(window2, function onWindow() { + let notification1 = document.getElementById("global-notificationbox"); + let notification2 = window2.document.getElementById("global-notificationbox"); + ok(notification2, "2nd window has a global notification box."); + + let [policy, promise] = sendNotifyRequest("multiple_window_behavior"); + let displayCount = 0; + let prefWindowOpened = false; + let mutationObserversRemoved = false; + + function onAlertDisplayed() { + displayCount++; + + if (displayCount != 2) { + return; + } + + ok(true, "Data reporting info bar displayed on all open windows."); + + // We register two independent observers and we need both to clean up + // properly. This handles gating for test completion. + function maybeFinish() { + if (!prefWindowOpened) { + dump("Not finishing test yet because pref pane hasn't yet appeared.\n"); + return; + } + + if (!mutationObserversRemoved) { + dump("Not finishing test yet because mutation observers haven't been removed yet.\n"); + return; + } + + window2.close(); + + dump("Finishing multiple window test.\n"); + rootLogger.removeAppender(dumpAppender); + dumpAppender = null; + rootLogger = null; + finish(); + } + let closeCount = 0; + + function onAlertClose() { + closeCount++; + + if (closeCount != 2) { + return; + } + + ok(true, "Closing info bar on one window closed them on all."); + is(policy.userNotifiedOfCurrentPolicy, true, "Data submission policy accepted."); + + is(notification1.allNotifications.length, 0, "No notifications remain on main window."); + is(notification2.allNotifications.length, 0, "No notifications remain on 2nd window."); + + mutationObserversRemoved = true; + maybeFinish(); + } + + waitForNotificationClose(notification1.currentNotification, onAlertClose); + waitForNotificationClose(notification2.currentNotification, onAlertClose); + + // While we're here, we dual purpose this test to check that pressing the + // button does the right thing. + let buttons = notification2.currentNotification.getElementsByTagName("button"); + is(buttons.length, 1, "There is 1 button in the data reporting notification."); + let button = buttons[0]; + + // Add an observer to ensure the "advanced" pane opened (but don't bother + // closing it - we close the entire window when done.) + Services.obs.addObserver(function observer(prefWin, topic, data) { + Services.obs.removeObserver(observer, "advanced-pane-loaded"); + + ok(true, "Advanced preferences opened on info bar button press."); + executeSoon(function soon() { + prefWindowOpened = true; + maybeFinish(); + }); + }, "advanced-pane-loaded", false); + + button.click(); + } + + notification1.addEventListener("AlertActive", function active1() { + notification1.removeEventListener("AlertActive", active1, true); + executeSoon(onAlertDisplayed); + }, true); + + notification2.addEventListener("AlertActive", function active2() { + notification2.removeEventListener("AlertActive", active2, true); + executeSoon(onAlertDisplayed); + }, true); + + promise.then(null, function onError(err) { + throw err; + }); + }); +} + +function cleanup () { + // In case some test fails. + if (originalPolicy) { + let service = Cc["@mozilla.org/datareporting/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject; + service.policy = originalPolicy; + } + + return closeAllNotifications(); +} diff --git a/browser/base/content/test/general/browser_urlbarSearchTelemetry.js b/browser/base/content/test/general/browser_urlbarSearchTelemetry.js index 98243ac9d25..21a8ed7e19c 100644 --- a/browser/base/content/test/general/browser_urlbarSearchTelemetry.js +++ b/browser/base/content/test/general/browser_urlbarSearchTelemetry.js @@ -103,6 +103,7 @@ function* compareCounts(clickCallback) { // FHR -- first make sure the engine has an identifier so that FHR is happy. Object.defineProperty(engine.wrappedJSObject, "identifier", { value: engineID }); + let fhrCount = yield getNumberOfSearchesInFHR(engine.name, "urlbar"); gURLBar.focus(); yield clickCallback(); @@ -125,6 +126,10 @@ function* compareCounts(clickCallback) { Assert.ok(histogramKey in snapshot, "histogram with key should be recorded"); Assert.equal(snapshot[histogramKey].sum, histogramCount + 1, "histogram sum should be incremented"); + + // FHR + let newFHRCount = yield getNumberOfSearchesInFHR(engine.name, "urlbar"); + Assert.equal(newFHRCount, fhrCount + 1, "should be recorded in FHR"); } /** diff --git a/browser/base/content/test/general/browser_urlbar_search_healthreport.js b/browser/base/content/test/general/browser_urlbar_search_healthreport.js new file mode 100644 index 00000000000..6a37a80fb5d --- /dev/null +++ b/browser/base/content/test/general/browser_urlbar_search_healthreport.js @@ -0,0 +1,85 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(function* test_healthreport_search_recording() { + try { + let cm = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); + cm.getCategoryEntry("healthreport-js-provider-default", "SearchesProvider"); + } catch (ex) { + // Health Report disabled, or no SearchesProvider. + ok(true, "Firefox Health Report is not enabled."); + return; + } + + let reporter = Cc["@mozilla.org/datareporting/service;1"] + .getService() + .wrappedJSObject + .healthReporter; + ok(reporter, "Health Reporter available."); + yield reporter.onInit(); + let provider = reporter.getProvider("org.mozilla.searches"); + ok(provider, "Searches provider is available."); + let m = provider.getMeasurement("counts", 3); + + let data = yield m.getValues(); + let now = new Date(); + let oldCount = 0; + + // This will to be need changed if default search engine is not Google. + // Note: geoSpecificDefaults are disabled for mochitests, so this is the + // non-US en-US default. + let defaultEngineID = "google"; + + let field = defaultEngineID + ".urlbar"; + + if (data.days.hasDay(now)) { + let day = data.days.getDay(now); + if (day.has(field)) { + oldCount = day.get(field); + } + } + + let tab = gBrowser.addTab("about:blank"); + yield BrowserTestUtils.browserLoaded(tab.linkedBrowser); + gBrowser.selectedTab = tab; + + let searchStr = "firefox health report"; + let expectedURL = Services.search.currentEngine. + getSubmission(searchStr, "", "keyword").uri.spec; + + // Expect the search URL to load but stop it as soon as it starts. + let docLoadPromise = waitForDocLoadAndStopIt(expectedURL); + + // Trigger the search. + gURLBar.value = searchStr; + gURLBar.handleCommand(); + + yield docLoadPromise; + + data = yield m.getValues(); + ok(data.days.hasDay(now), "We have a search measurement for today."); + let day = data.days.getDay(now); + ok(day.has(field), "Have a search count for the urlbar."); + let newCount = day.get(field); + is(newCount, oldCount + 1, "We recorded one new search."); + + // We should record the default search engine if Telemetry is enabled. + let oldTelemetry = Services.prefs.getBoolPref("toolkit.telemetry.enabled"); + Services.prefs.setBoolPref("toolkit.telemetry.enabled", true); + + m = provider.getMeasurement("engines", 2); + yield provider.collectDailyData(); + data = yield m.getValues(); + + ok(data.days.hasDay(now), "Have engines data when Telemetry is enabled."); + day = data.days.getDay(now); + ok(day.has("default"), "We have default engine data."); + is(day.get("default"), defaultEngineID, "The default engine is reported properly."); + + // Restore. + Services.prefs.setBoolPref("toolkit.telemetry.enabled", oldTelemetry); + + gBrowser.removeTab(tab); +}); diff --git a/browser/base/content/test/general/head.js b/browser/base/content/test/general/head.js index 2f20399e19a..4e5f98f5a07 100644 --- a/browser/base/content/test/general/head.js +++ b/browser/base/content/test/general/head.js @@ -1202,3 +1202,61 @@ function promiseCrashReport(expectedExtra) { } }); } + +/** + * Retrieves the number of searches recorded in FHR for the current day. + * + * @param aEngineName + * name of the setup search engine. + * @param aSource + * The FHR "source" name for the search, like "abouthome" or "urlbar". + * + * @return {Promise} Returns a promise resolving to the number of searches. + */ +function getNumberOfSearchesInFHR(aEngineName, aSource) { + let reporter = Components.classes["@mozilla.org/datareporting/service;1"] + .getService() + .wrappedJSObject + .healthReporter; + ok(reporter, "Health Reporter instance available."); + + return reporter.onInit().then(function onInit() { + let provider = reporter.getProvider("org.mozilla.searches"); + ok(provider, "Searches provider is available."); + + let m = provider.getMeasurement("counts", 3); + return m.getValues().then(data => { + let now = new Date(); + let yday = new Date(now); + yday.setDate(yday.getDate() - 1); + + // Add the number of searches recorded yesterday to the number of searches + // recorded today. This makes the test not fail intermittently when it is + // run at midnight and we accidentally compare the number of searches from + // different days. Tests are always run with an empty profile so there + // are no searches from yesterday, normally. Should the test happen to run + // past midnight we make sure to count them in as well. + return getNumberOfSearchesInFHRByDate(aEngineName, aSource, data, now) + + getNumberOfSearchesInFHRByDate(aEngineName, aSource, data, yday); + }); + }); +} + +/** + * Helper for getNumberOfSearchesInFHR. You probably don't want to call this + * directly. + */ +function getNumberOfSearchesInFHRByDate(aEngineName, aSource, aData, aDate) { + if (aData.days.hasDay(aDate)) { + let id = Services.search.getEngineByName(aEngineName).identifier; + + let day = aData.days.getDay(aDate); + let field = id + "." + aSource; + + if (day.has(field)) { + return day.get(field) || 0; + } + } + + return 0; // No records found. +} diff --git a/browser/base/content/test/general/healthreport_testRemoteCommands.html b/browser/base/content/test/general/healthreport_testRemoteCommands.html index 7978914f2be..cc9e7076708 100644 --- a/browser/base/content/test/general/healthreport_testRemoteCommands.html +++ b/browser/base/content/test/general/healthreport_testRemoteCommands.html @@ -7,14 +7,35 @@