mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into mozilla-inbound
This commit is contained in:
commit
46c6a08469
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1357164966000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1357926611000">
|
||||
<emItems>
|
||||
<emItem blockID="i58" id="webmaster@buzzzzvideos.info">
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
@ -588,42 +588,42 @@
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p180">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 07" maxVersion="Java 7 Update 08" severity="0" vulnerabilitystatus="1">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 7 Update 0" maxVersion="Java 7 Update 10" severity="0" vulnerabilitystatus="2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p182">
|
||||
<match name="name" exp="Java\(TM\) Platform SE 7 U[7-8](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<match name="name" exp="Java\(TM\) Platform SE 7 U([0-9]|10)(\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p184">
|
||||
<match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([7-8]))?([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<match name="name" exp="Java\(TM\) Plug-in 1\.7\.0(_0?([0-9]|10)?)?([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p186">
|
||||
<match name="name" exp="Java\(TM\) Platform SE 6 U3[3-6](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<match name="name" exp="Java\(TM\) Platform SE 6 U3[1-8](\s[^\d\._U]|$)" /> <match name="filename" exp="npjp2\.dll" /> <versionRange severity="0" vulnerabilitystatus="2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p188">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 0" maxVersion="Java 6 Update 36" severity="0" vulnerabilitystatus="1">
|
||||
<match name="filename" exp="JavaAppletPlugin\.plugin" /> <versionRange minVersion="Java 6 Update 0" maxVersion="Java 6 Update 38" severity="0" vulnerabilitystatus="2">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
</versionRange>
|
||||
</pluginItem>
|
||||
<pluginItem blockID="p190">
|
||||
<match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_3[3-6]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<match name="name" exp="Java\(TM\) Plug-in 1\.6\.0_3[1-8]([^\d\._]|$)" /> <match name="filename" exp="libnpjp2\.so" /> <versionRange severity="0" vulnerabilitystatus="1">
|
||||
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
|
||||
<versionRange minVersion="17.0" maxVersion="*" />
|
||||
</targetApplication>
|
||||
|
@ -865,6 +865,10 @@ pref("breakpad.reportURL", "http://crash-stats.mozilla.com/report/index/");
|
||||
pref("toolkit.crashreporter.pluginHangSubmitURL",
|
||||
"https://hang-reports.mozilla.org/submit");
|
||||
|
||||
// URL for "Learn More" for Crash Reporter
|
||||
pref("toolkit.crashreporter.infoURL",
|
||||
"http://www.mozilla.com/legal/privacy/firefox.html#crash-reporter");
|
||||
|
||||
// base URL for web-based support pages
|
||||
pref("app.support.baseURL", "http://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
|
||||
|
||||
|
140
browser/base/content/abouthealthreport/abouthealth.css
Normal file
140
browser/base/content/abouthealthreport/abouthealth.css
Normal file
@ -0,0 +1,140 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: window;
|
||||
color: windowtext;
|
||||
font-family: "Trebuchet MS", "Helvetica";
|
||||
}
|
||||
|
||||
#about-header {
|
||||
padding: 6px 20px;
|
||||
min-height: 60px;
|
||||
border-bottom: 1px solid #999999;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-image: linear-gradient(to bottom, #E66000, #BB2200);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
#control-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#content-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#state-intro {
|
||||
background-image: linear-gradient(to bottom, #EAEFF2, #D4DDE4);
|
||||
border: 1px solid #999999;
|
||||
border-radius: 6px;
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#settings-controls {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
#control-container {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
#content[state="default"] #details-hide,
|
||||
#content[state="default"] #btn-optin,
|
||||
#content[state="default"] #intro-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#content[state="showDetails"] #details-show,
|
||||
#content[state="showDetails"] #btn-optin,
|
||||
#content[state="showDetails"] #intro-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#content[state="showReport"] #details-hide,
|
||||
#content[state="showReport"] #report-show,
|
||||
#content[state="showReport"] #btn-optin,
|
||||
#content[state="showReport"] #intro-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#content[state="disabled"] #details-hide,
|
||||
#content[state="disabled"] #details-show,
|
||||
#content[state="disabled"] #btn-optout,
|
||||
#content[state="disabled"] #intro-enabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#details-view,
|
||||
#report-view {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#data-view {
|
||||
height: auto;
|
||||
margin-top: 8px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #999999;
|
||||
border-radius: 6px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
#remote-report,
|
||||
#report-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
#report-show {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 60px;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
background-image: linear-gradient(to bottom, #80BB2E, #547D1C);
|
||||
color: #ffffff;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#details-view {
|
||||
border: 1px solid #999999;
|
||||
border-radius: 6px;
|
||||
margin: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#content[state="showDetails"],
|
||||
#content[state="showReport"],
|
||||
#content[state="showDetails"] #details-view,
|
||||
#content[state="showReport"] #report-view {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content[state="showReport"] #report-show {
|
||||
display: none;
|
||||
}
|
||||
#content[state="showReport"] #report-view,
|
||||
#remote-report {
|
||||
border: 0;
|
||||
}
|
117
browser/base/content/abouthealthreport/abouthealth.js
Normal file
117
browser/base/content/abouthealthreport/abouthealth.js
Normal file
@ -0,0 +1,117 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
|
||||
const reporter = Cc["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject
|
||||
.healthReporter;
|
||||
|
||||
const policy = Cc["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject.policy;
|
||||
|
||||
const prefs = new Preferences("datareporting.healthreport.about.");
|
||||
|
||||
function getLocale() {
|
||||
return Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Ci.nsIXULChromeRegistry)
|
||||
.getSelectedLocale("global");
|
||||
}
|
||||
|
||||
function init() {
|
||||
refreshWithDataSubmissionFlag(reporter.willUploadData);
|
||||
refreshJSONPayload();
|
||||
document.getElementById("details-link").href = prefs.get("glossaryUrl");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state of the page to reflect the current data submission state.
|
||||
*
|
||||
* @param enabled
|
||||
* (bool) Whether data submission is enabled.
|
||||
*/
|
||||
function refreshWithDataSubmissionFlag(enabled) {
|
||||
if (!enabled)
|
||||
updateView("disabled");
|
||||
else
|
||||
updateView("default");
|
||||
}
|
||||
|
||||
function updateView(state="default") {
|
||||
let content = document.getElementById("content");
|
||||
let controlContainer = document.getElementById("control-container");
|
||||
content.setAttribute("state", state);
|
||||
controlContainer.setAttribute("state", state);
|
||||
}
|
||||
|
||||
function refreshDataView(data) {
|
||||
let noData = document.getElementById("data-no-data");
|
||||
let dataEl = document.getElementById("raw-data");
|
||||
|
||||
noData.style.display = data ? "none" : "inline";
|
||||
dataEl.style.display = data ? "block" : "none";
|
||||
if (data)
|
||||
dataEl.innerHTML = JSON.stringify(data, null, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the page has the latest version of the uploaded JSON payload.
|
||||
*/
|
||||
function refreshJSONPayload() {
|
||||
reporter.getLastPayload().then(refreshDataView);
|
||||
}
|
||||
|
||||
function onOptInClick() {
|
||||
policy.healthReportUploadEnable = true;
|
||||
refreshWithDataSubmissionFlag(true);
|
||||
}
|
||||
|
||||
function onOptOutClick() {
|
||||
let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Ci.nsIPromptService);
|
||||
|
||||
let messages = document.getElementById("optout-confirmationPrompt");
|
||||
let title = messages.getAttribute("confirmationPrompt_title");
|
||||
let message = messages.getAttribute("confirmationPrompt_message");
|
||||
|
||||
if (!prompts.confirm(window, title, message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
policy.healthReportUploadEnable = false;
|
||||
let promise = reporter.requestDeleteRemoteData("Clicked opt out button on about page.");
|
||||
if (promise) {
|
||||
promise.then(function onDelete() {
|
||||
refreshWithDataSubmissionFlag(reporter.willUploadData);
|
||||
});
|
||||
}
|
||||
|
||||
refreshWithDataSubmissionFlag(false);
|
||||
updateView("disabled");
|
||||
}
|
||||
|
||||
function onShowRawDataClick() {
|
||||
updateView("showDetails");
|
||||
refreshJSONPayload();
|
||||
}
|
||||
|
||||
function onHideRawDataClick() {
|
||||
updateView("default");
|
||||
}
|
||||
|
||||
function onShowReportClick() {
|
||||
updateView("showReport");
|
||||
document.getElementById("remote-report").src = prefs.get("reportUrl");
|
||||
}
|
||||
|
||||
function onHideReportClick() {
|
||||
updateView("default");
|
||||
document.getElementById("remote-report").src = "";
|
||||
}
|
71
browser/base/content/abouthealthreport/abouthealth.xhtml
Normal file
71
browser/base/content/abouthealthreport/abouthealth.xhtml
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
|
||||
%htmlDTD;
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%brandDTD;
|
||||
<!ENTITY % securityPrefsDTD SYSTEM "chrome://browser/locale/preferences/security.dtd">
|
||||
%securityPrefsDTD;
|
||||
<!ENTITY % aboutHealthReportDTD SYSTEM "chrome://browser/locale/aboutHealthReport.dtd">
|
||||
%aboutHealthReportDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&abouthealth.pagetitle;</title>
|
||||
<link rel="stylesheet"
|
||||
href="chrome://browser/content/abouthealthreport/abouthealth.css"
|
||||
type="text/css" />
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/abouthealthreport/abouthealth.js" />
|
||||
</head>
|
||||
<body dir="&abouthealth.locale-direction;" class="aboutPageWideContainer" onload="init();">
|
||||
<div id="about-header">
|
||||
<h1>&abouthealth.header;</h1>
|
||||
<img src="chrome://branding/content/icon48.png"/>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div id="state-intro">
|
||||
<h3>&abouthealth.intro.title;</h3>
|
||||
<div id="content-line">
|
||||
<p id="intro-enabled">&abouthealth.intro-enabled;</p>
|
||||
<p id="intro-disabled">&abouthealth.intro-disabled;</p>
|
||||
<div id="control-container">
|
||||
<button id="btn-optin" onclick="onOptInClick();">&abouthealth.optin;</button>
|
||||
<button id="btn-optout" onclick="onOptOutClick();">&abouthealth.optout;</button>
|
||||
|
||||
<button id="details-show" onclick="onShowRawDataClick()">&abouthealth.show-raw-data;</button>
|
||||
<button id="details-hide" onclick="onHideRawDataClick()">&abouthealth.hide-raw-data;</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="details-view">
|
||||
<p id="details-description">
|
||||
&abouthealth.details.description-start;
|
||||
<a id="details-link">&abouthealth.details-link;</a>
|
||||
&abouthealth.details.description-end;
|
||||
</p>
|
||||
|
||||
<p id="data-no-data">&abouthealth.no-data-available;</p>
|
||||
<pre id="raw-data" style="display: none"></pre>
|
||||
</div>
|
||||
|
||||
<div id="data-view">
|
||||
<button id="report-show" onclick="onShowReportClick()">&abouthealth.show-report;</button>
|
||||
<div id="report-view">
|
||||
<iframe id="remote-report"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="optout-confirmationPrompt"
|
||||
confirmationPrompt_title="&abouthealth.optout.confirmationPrompt.title;"
|
||||
confirmationPrompt_message="&abouthealth.optout.confirmationPrompt.message;"
|
||||
/>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -52,6 +52,11 @@
|
||||
#else
|
||||
/>
|
||||
#endif
|
||||
<menuitem id="healthReport"
|
||||
label="&healthReport.label;"
|
||||
accesskey="&healthReport.accesskey;"
|
||||
oncommand="openHealthReport()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="troubleShooting"
|
||||
accesskey="&helpTroubleshootingInfo.accesskey;"
|
||||
label="&helpTroubleshootingInfo.label;"
|
||||
|
@ -378,6 +378,10 @@
|
||||
label="&appMenuGettingStarted.label;"
|
||||
oncommand="gBrowser.loadOneTab('http://www.mozilla.com/firefox/central/', {inBackground: false});"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="appmenu_healthReport"
|
||||
label="&healthReport.label;"
|
||||
oncommand="openHealthReport()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="appmenu_troubleshootingInfo"
|
||||
label="&helpTroubleshootingInfo.label;"
|
||||
oncommand="openTroubleshootingPage()"
|
||||
|
171
browser/base/content/browser-data-submission-info-bar.js
Normal file
171
browser/base/content/browser-data-submission-info-bar.js
Normal file
@ -0,0 +1,171 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
Cu.import("resource://services-common/log4moz.js");
|
||||
|
||||
/**
|
||||
* Represents an info bar that shows a data submission notification.
|
||||
*/
|
||||
function DataNotificationInfoBar() {
|
||||
let log4moz = Cu.import("resource://services-common/log4moz.js", {}).Log4Moz;
|
||||
this._log = log4moz.repository.getLogger("Services.DataReporting.InfoBar");
|
||||
|
||||
this._notificationBox = null;
|
||||
}
|
||||
|
||||
DataNotificationInfoBar.prototype = {
|
||||
_OBSERVERS: [
|
||||
"datareporting:notify-data-policy:request",
|
||||
"datareporting:notify-data-policy:close",
|
||||
],
|
||||
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
_PREF_TELEMETRY_DISPLAYED: "toolkit.telemetry.notifiedOptOut",
|
||||
#else
|
||||
_PREF_TELEMETRY_DISPLAYED: "toolkit.telemetry.prompted",
|
||||
#endif
|
||||
|
||||
_TELEMETRY_DISPLAY_REV: 2,
|
||||
#endif
|
||||
|
||||
init: function() {
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload, false);
|
||||
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.removeObserver(this, o);
|
||||
}
|
||||
}.bind(this), false);
|
||||
|
||||
for (let o of this._OBSERVERS) {
|
||||
Services.obs.addObserver(this, o, true);
|
||||
}
|
||||
},
|
||||
|
||||
_ensureNotificationBox: function () {
|
||||
if (this._notificationBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
let nb = document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"notificationbox"
|
||||
);
|
||||
nb.id = "data-notification-notify-bar";
|
||||
nb.setAttribute("flex", "1");
|
||||
|
||||
let bottombox = document.getElementById("browser-bottombox");
|
||||
bottombox.insertBefore(nb, bottombox.firstChild);
|
||||
|
||||
this._notificationBox = nb;
|
||||
},
|
||||
|
||||
_displayDataPolicyInfoBar: function (request) {
|
||||
this._ensureNotificationBox();
|
||||
|
||||
if (this._notificationBox.getNotificationWithValue("data-reporting")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let policy = Cc["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
let appName = brandBundle.getString("brandShortName");
|
||||
let vendorName = brandBundle.getString("vendorShortName");
|
||||
|
||||
let message = gNavigatorBundle.getFormattedString(
|
||||
"dataReportingNotification.message",
|
||||
[appName, vendorName]);
|
||||
|
||||
let actionTaken = false;
|
||||
|
||||
let buttons = [{
|
||||
label: gNavigatorBundle.getString("dataReportingNotification.button.label"),
|
||||
accesskey: gNavigatorBundle.getString("dataReportingNotification.button.accessKey"),
|
||||
popup: null,
|
||||
callback: function () {
|
||||
// Clicking the button to go to the preferences tab constitutes
|
||||
// acceptance of the data upload policy for Firefox Health Report.
|
||||
// This will ensure the checkbox is checked. The user has the option of
|
||||
// unchecking it.
|
||||
request.onUserAccept("info-bar-button-pressed");
|
||||
actionTaken = true;
|
||||
window.openAdvancedPreferences("dataChoicesTab");
|
||||
},
|
||||
}];
|
||||
|
||||
this._log.info("Creating data reporting policy notification.");
|
||||
let notification = this._notificationBox.appendNotification(
|
||||
message,
|
||||
"data-reporting",
|
||||
null,
|
||||
this._notificationBox.PRIORITY_INFO_HIGH,
|
||||
buttons,
|
||||
function onEvent(event) {
|
||||
if (event == "removed") {
|
||||
if (!actionTaken) {
|
||||
request.onUserAccept("info-bar-dismissed");
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "datareporting:notify-data-policy:close", null);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
// Keep open until user closes it.
|
||||
notification.persistence = -1;
|
||||
|
||||
// This likely isn't needed in a world where Telemetry and FHR share a
|
||||
// notification and data reporting policy. It is preserved until traces
|
||||
// of this pref are wiped from the code base.
|
||||
Services.prefs.setIntPref(this._PREF_TELEMETRY_DISPLAYED,
|
||||
this._TELEMETRY_DISPLAY_REV);
|
||||
|
||||
// Tell the notification request we have displayed the notification.
|
||||
request.onUserNotifyComplete();
|
||||
},
|
||||
|
||||
_clearPolicyNotification: function () {
|
||||
if (!this._notificationBox ||
|
||||
!this._notificationBox.getNotificationWithValue("data-reporting")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._notificationBox.getNotificationWithValue("date-reporting").close();
|
||||
},
|
||||
|
||||
onNotifyDataPolicy: function (request) {
|
||||
try {
|
||||
this._displayDataPolicyInfoBar(request);
|
||||
} catch (ex) {
|
||||
request.onUserNotifyFailed(ex);
|
||||
}
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "datareporting:notify-data-policy:request":
|
||||
this.onNotifyDataPolicy(subject.wrappedJSObject.object);
|
||||
break;
|
||||
|
||||
case "datareporting:notify-data-policy:close":
|
||||
this._clearPolicyNotification();
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference,
|
||||
]),
|
||||
};
|
||||
|
@ -157,6 +157,12 @@ let gInitialPages = [
|
||||
#include browser-thumbnails.js
|
||||
#include browser-webrtcUI.js
|
||||
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
#include browser-data-submission-info-bar.js
|
||||
|
||||
let gDataNotificationInfoBar = new DataNotificationInfoBar();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
#include browser-syncui.js
|
||||
#endif
|
||||
@ -1395,6 +1401,10 @@ var gBrowserInit = {
|
||||
gSyncUI.init();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
gDataNotificationInfoBar.init();
|
||||
#endif
|
||||
|
||||
gBrowserThumbnails.init();
|
||||
TabView.init();
|
||||
|
||||
|
@ -529,6 +529,16 @@ function openTroubleshootingPage()
|
||||
openUILinkIn("about:support", "tab");
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the troubleshooting information (about:support) page for this version
|
||||
* of the application.
|
||||
*/
|
||||
function openHealthReport()
|
||||
{
|
||||
openUILinkIn("about:healthreport", "tab");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens the feedback page for this version of the application.
|
||||
*/
|
||||
|
@ -48,6 +48,11 @@ browser.jar:
|
||||
content/browser/abouthome/restore@2x.png (content/abouthome/restore@2x.png)
|
||||
content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png)
|
||||
content/browser/abouthome/mozilla@2x.png (content/abouthome/mozilla@2x.png)
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
content/browser/abouthealthreport/abouthealth.xhtml (content/abouthealthreport/abouthealth.xhtml)
|
||||
content/browser/abouthealthreport/abouthealth.js (content/abouthealthreport/abouthealth.js)
|
||||
content/browser/abouthealthreport/abouthealth.css (content/abouthealthreport/abouthealth.css)
|
||||
#endif
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
|
@ -82,6 +82,10 @@ static RedirEntry kRedirMap[] = {
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
{ "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
};
|
||||
static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);
|
||||
|
||||
|
@ -117,6 +117,9 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
|
||||
#elif defined(XP_MACOSX)
|
||||
|
@ -438,11 +438,6 @@ BrowserGlue.prototype = {
|
||||
// Show about:rights notification, if needed.
|
||||
if (this._shouldShowRights()) {
|
||||
this._showRightsNotification();
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
} else {
|
||||
// Only show telemetry notification when about:rights notification is not shown.
|
||||
this._showTelemetryNotification();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Show update notification, if needed.
|
||||
@ -506,7 +501,7 @@ BrowserGlue.prototype = {
|
||||
var win = this.getMostRecentBrowserWindow();
|
||||
var brandBundle = win.document.getElementById("bundle_brand");
|
||||
var shellBundle = win.document.getElementById("bundle_shell");
|
||||
|
||||
|
||||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
var promptTitle = shellBundle.getString("setDefaultBrowserTitle");
|
||||
var promptMessage = shellBundle.getFormattedString("setDefaultBrowserMessage",
|
||||
@ -857,167 +852,6 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
_showTelemetryNotification: function BG__showTelemetryNotification() {
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabledPreRelease";
|
||||
const PREF_TELEMETRY_DISPLAYED = "toolkit.telemetry.notifiedOptOut";
|
||||
#else
|
||||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
|
||||
const PREF_TELEMETRY_DISPLAYED = "toolkit.telemetry.prompted";
|
||||
#endif
|
||||
const PREF_TELEMETRY_REJECTED = "toolkit.telemetry.rejected";
|
||||
const PREF_TELEMETRY_INFOURL = "toolkit.telemetry.infoURL";
|
||||
const PREF_TELEMETRY_SERVER_OWNER = "toolkit.telemetry.server_owner";
|
||||
// This is used to reprompt/renotify users when privacy message changes
|
||||
const TELEMETRY_DISPLAY_REV = @MOZ_TELEMETRY_DISPLAY_REV@;
|
||||
|
||||
// Stick notifications onto the selected tab of the active browser window.
|
||||
var win = this.getMostRecentBrowserWindow();
|
||||
var tabbrowser = win.gBrowser;
|
||||
var notifyBox = tabbrowser.getNotificationBox();
|
||||
|
||||
var browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
var productName = brandBundle.GetStringFromName("brandFullName");
|
||||
var serverOwner = Services.prefs.getCharPref(PREF_TELEMETRY_SERVER_OWNER);
|
||||
|
||||
function appendTelemetryNotification(message, buttons, hideclose) {
|
||||
let notification = notifyBox.appendNotification(message, "telemetry", null,
|
||||
notifyBox.PRIORITY_INFO_LOW,
|
||||
buttons);
|
||||
if (hideclose)
|
||||
notification.setAttribute("hideclose", hideclose);
|
||||
notification.persistence = -1; // Until user closes it
|
||||
return notification;
|
||||
}
|
||||
|
||||
function appendLearnMoreLink(notification) {
|
||||
let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
link.className = "text-link telemetry-text-link";
|
||||
link.setAttribute("value", browserBundle.GetStringFromName("telemetryLinkLabel"));
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
return link;
|
||||
}
|
||||
|
||||
/*
|
||||
* Display an opt-out notification when telemetry is enabled by default,
|
||||
* an opt-in prompt otherwise.
|
||||
*
|
||||
* But do not display this prompt/notification if:
|
||||
*
|
||||
* - The last accepted/refused policy (either by accepting the prompt or by
|
||||
* manually flipping the telemetry preference) is already at version
|
||||
* TELEMETRY_DISPLAY_REV or higher (to avoid the prompt in tests).
|
||||
*/
|
||||
var telemetryDisplayed;
|
||||
try {
|
||||
telemetryDisplayed = Services.prefs.getIntPref(PREF_TELEMETRY_DISPLAYED);
|
||||
} catch(e) {}
|
||||
if (telemetryDisplayed >= TELEMETRY_DISPLAY_REV)
|
||||
return;
|
||||
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
/*
|
||||
* Additionally, in opt-out builds, don't display the notification if:
|
||||
*
|
||||
* - Telemetry is disabled
|
||||
* - Telemetry was explicitly refused through the UI
|
||||
* - Opt-in telemetry was already enabled, don't notify the user until next
|
||||
* policy update. (Do the check only at first run with opt-out builds)
|
||||
*/
|
||||
|
||||
var telemetryEnabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
|
||||
if (!telemetryEnabled)
|
||||
return;
|
||||
|
||||
// If telemetry was explicitly refused through the UI,
|
||||
// also disable opt-out telemetry and bail out.
|
||||
var telemetryRejected = false;
|
||||
try {
|
||||
telemetryRejected = Services.prefs.getBoolPref(PREF_TELEMETRY_REJECTED);
|
||||
} catch(e) {}
|
||||
if (telemetryRejected) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false);
|
||||
Services.prefs.setIntPref(PREF_TELEMETRY_DISPLAYED, TELEMETRY_DISPLAY_REV);
|
||||
return;
|
||||
}
|
||||
|
||||
// If opt-in telemetry was enabled and this is the first run with opt-out,
|
||||
// don't notify the user.
|
||||
var optInTelemetryEnabled = false;
|
||||
try {
|
||||
optInTelemetryEnabled = Services.prefs.getBoolPref("toolkit.telemetry.enabled");
|
||||
} catch(e) {}
|
||||
if (optInTelemetryEnabled && telemetryDisplayed === undefined) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_REJECTED, false);
|
||||
Services.prefs.setIntPref(PREF_TELEMETRY_DISPLAYED, TELEMETRY_DISPLAY_REV);
|
||||
return;
|
||||
}
|
||||
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryOptOutPrompt",
|
||||
[productName, serverOwner, productName], 3);
|
||||
var buttons = null;
|
||||
var hideCloseButton = false;
|
||||
function learnModeClickHandler() {
|
||||
// Open the learn more url in a new tab
|
||||
var url = Services.urlFormatter.formatURLPref("app.support.baseURL");
|
||||
url += "how-can-i-help-submitting-performance-data";
|
||||
tabbrowser.selectedTab = tabbrowser.addTab(url);
|
||||
// Remove the notification on which the user clicked
|
||||
notification.parentNode.removeNotification(notification, true);
|
||||
}
|
||||
#else
|
||||
|
||||
// Clear old prefs and reprompt
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_REJECTED);
|
||||
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryOptInPrompt",
|
||||
[productName, serverOwner], 2);
|
||||
var buttons = [
|
||||
{
|
||||
label: browserBundle.GetStringFromName("telemetryYesButtonLabel2"),
|
||||
accessKey: browserBundle.GetStringFromName("telemetryYesButtonAccessKey"),
|
||||
popup: null,
|
||||
callback: function(aNotificationBar, aButton) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, true);
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_REJECTED, false);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: browserBundle.GetStringFromName("telemetryNoButtonLabel"),
|
||||
accessKey: browserBundle.GetStringFromName("telemetryNoButtonAccessKey"),
|
||||
popup: null,
|
||||
callback: function(aNotificationBar, aButton) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_REJECTED, true);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var hideCloseButton = true;
|
||||
function learnModeClickHandler() {
|
||||
// Open the learn more url in a new tab
|
||||
win.openUILinkIn(Services.prefs.getCharPref(PREF_TELEMETRY_INFOURL), "tab");
|
||||
// Remove the notification on which the user clicked
|
||||
notification.parentNode.removeNotification(notification, true);
|
||||
// Add a new notification to that tab, with no "Learn more" link
|
||||
notifyBox = tabbrowser.getNotificationBox();
|
||||
appendTelemetryNotification(telemetryPrompt, buttons, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set pref to indicate we've shown the notification.
|
||||
Services.prefs.setIntPref(PREF_TELEMETRY_DISPLAYED, TELEMETRY_DISPLAY_REV);
|
||||
|
||||
var notification = appendTelemetryNotification(telemetryPrompt, buttons, hideCloseButton);
|
||||
var link = appendLearnMoreLink(notification);
|
||||
link.addEventListener('click', learnModeClickHandler, false);
|
||||
},
|
||||
#endif
|
||||
|
||||
_showPluginUpdatePage: function BG__showPluginUpdatePage() {
|
||||
Services.prefs.setBoolPref(PREF_PLUGINS_NOTIFYUSER, false);
|
||||
|
||||
|
@ -48,9 +48,11 @@ var gAdvancedPane = {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
this.initSubmitCrashes();
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
this.initTelemetry();
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
this.initSubmitHealthReport();
|
||||
#endif
|
||||
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize("offline");
|
||||
|
||||
@ -129,6 +131,36 @@ var gAdvancedPane = {
|
||||
return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* When the user toggles the layers.acceleration.disabled pref,
|
||||
* sync its new value to the gfx.direct2d.disabled pref too.
|
||||
*/
|
||||
updateHardwareAcceleration: function()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
var fromPref = document.getElementById("layers.acceleration.disabled");
|
||||
var toPref = document.getElementById("gfx.direct2d.disabled");
|
||||
toPref.value = fromPref.value;
|
||||
#endif
|
||||
},
|
||||
|
||||
// DATA CHOICES TAB
|
||||
|
||||
/**
|
||||
* Set up or hide the Learn More links for various data collection options
|
||||
*/
|
||||
_setupLearnMoreLink: function (pref, element) {
|
||||
// set up the Learn More link with the correct URL
|
||||
let url = Services.prefs.getCharPref(pref);
|
||||
let el = document.getElementById(element);
|
||||
|
||||
if (url) {
|
||||
el.setAttribute("href", url);
|
||||
} else {
|
||||
el.setAttribute("hidden", "true");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -142,6 +174,7 @@ var gAdvancedPane = {
|
||||
} catch (e) {
|
||||
checkbox.style.display = "none";
|
||||
}
|
||||
this._setupLearnMoreLink("toolkit.crashreporter.infoURL", "crashReporterLearnMore");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -157,16 +190,19 @@ var gAdvancedPane = {
|
||||
} catch (e) { }
|
||||
},
|
||||
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
|
||||
/**
|
||||
* When telemetry is opt-out, verify if the user explicitly rejected the
|
||||
* telemetry prompt, and if so reflect his choice in the current preference
|
||||
* value. This doesn't cover the case where the user refused telemetry in the
|
||||
* prompt but later enabled it in preferences in builds before the fix for
|
||||
* bug 737600.
|
||||
*
|
||||
* In all cases, set up the Learn More link sanely
|
||||
*/
|
||||
initTelemetry: function ()
|
||||
{
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabledPreRelease";
|
||||
let enabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
|
||||
let rejected = false;
|
||||
@ -176,8 +212,11 @@ var gAdvancedPane = {
|
||||
if (enabled && rejected) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false);
|
||||
}
|
||||
},
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
|
||||
#endif
|
||||
},
|
||||
|
||||
/**
|
||||
* When the user toggles telemetry, update the rejected value as well, so we
|
||||
@ -191,19 +230,46 @@ var gAdvancedPane = {
|
||||
displayed.value = @MOZ_TELEMETRY_DISPLAY_REV@;
|
||||
},
|
||||
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
/**
|
||||
* When the user toggles the layers.acceleration.disabled pref,
|
||||
* sync its new value to the gfx.direct2d.disabled pref too.
|
||||
* Initialize the health report service reference and checkbox.
|
||||
*/
|
||||
updateHardwareAcceleration: function()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
var fromPref = document.getElementById("layers.acceleration.disabled");
|
||||
var toPref = document.getElementById("gfx.direct2d.disabled");
|
||||
toPref.value = fromPref.value;
|
||||
#endif
|
||||
initSubmitHealthReport: function () {
|
||||
this._setupLearnMoreLink("datareporting.healthreport.infoURL", "FHRLearnMore");
|
||||
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
|
||||
let checkbox = document.getElementById("submitHealthReportBox");
|
||||
|
||||
if (!policy) {
|
||||
checkbox.setAttribute("disabled", "true");
|
||||
return;
|
||||
}
|
||||
|
||||
checkbox.checked = policy.healthReportUploadEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the health report policy acceptance with state from checkbox.
|
||||
*/
|
||||
updateSubmitHealthReport: function () {
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
|
||||
if (!policy) {
|
||||
return;
|
||||
}
|
||||
|
||||
let checkbox = document.getElementById("submitHealthReportBox");
|
||||
policy.healthReportUploadEnabled = checkbox.checked;
|
||||
},
|
||||
#endif
|
||||
|
||||
// NETWORK TAB
|
||||
|
||||
/*
|
||||
|
@ -50,6 +50,8 @@
|
||||
type="bool"/>
|
||||
#endif
|
||||
|
||||
<!-- Data Choices tab -->
|
||||
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<preference id="toolkit.telemetry.enabled"
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
@ -74,12 +76,12 @@
|
||||
<!-- Network tab -->
|
||||
<preference id="browser.cache.disk.capacity" name="browser.cache.disk.capacity" type="int"/>
|
||||
<preference id="browser.offline-apps.notify" name="browser.offline-apps.notify" type="bool"/>
|
||||
|
||||
|
||||
<preference id="browser.cache.disk.smart_size.enabled"
|
||||
name="browser.cache.disk.smart_size.enabled"
|
||||
inverted="true"
|
||||
type="bool"/>
|
||||
|
||||
|
||||
<!-- Update tab -->
|
||||
#ifdef MOZ_UPDATER
|
||||
<preference id="app.update.enabled" name="app.update.enabled" type="bool"/>
|
||||
@ -115,7 +117,7 @@
|
||||
name="security.disable_button.openDeviceManager"
|
||||
type="bool"/>
|
||||
</preferences>
|
||||
|
||||
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
<stringbundle id="bundleShell" src="chrome://browser/locale/shellservice.properties"/>
|
||||
<stringbundle id="bundleBrand" src="chrome://branding/locale/brand.properties"/>
|
||||
@ -128,6 +130,9 @@
|
||||
|
||||
<tabs id="tabsElement">
|
||||
<tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
<tab id="dataChoicesTab" label="&dataChoicesTab.label;" helpTopic="prefs-advanced-data-choices"/>
|
||||
#endif
|
||||
<tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
|
||||
<tab id="updateTab" label="&updateTab.label;" helpTopic="prefs-advanced-update"/>
|
||||
<tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
|
||||
@ -180,11 +185,11 @@
|
||||
preference="layout.spellcheckDefault"/>
|
||||
</groupbox>
|
||||
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
<!-- System Defaults -->
|
||||
<groupbox id="systemDefaultsGroup" orient="vertical">
|
||||
<caption label="&systemDefaults.label;"/>
|
||||
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
<checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
|
||||
label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
|
||||
flex="1"/>
|
||||
@ -197,20 +202,64 @@
|
||||
<description>&isDefault.label;</description>
|
||||
</deck>
|
||||
</hbox>
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<checkbox id="submitCrashesBox" flex="1"
|
||||
oncommand="gAdvancedPane.updateSubmitCrashes();"
|
||||
label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<checkbox id="submitTelemetryBox" flex="1"
|
||||
preference="toolkit.telemetry.enabled"
|
||||
label="&submitTelemetry.label;" accesskey="&submitTelemetry.accesskey;"/>
|
||||
#endif
|
||||
</groupbox>
|
||||
#endif
|
||||
</tabpanel>
|
||||
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
<!-- Data Choices -->
|
||||
<tabpanel id="dataChoicesPanel" orient="vertical">
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<groupbox>
|
||||
<caption label="&telemetrySection.label;"/>
|
||||
<description>&telemetryDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitTelemetryBox"
|
||||
preference="toolkit.telemetry.enabled"
|
||||
label="&enableTelemetry.label;"
|
||||
accesskey="&enableTelemetry.accesskey;"/>
|
||||
<spacer flex="1"/>
|
||||
<label id="telemetryLearnMore"
|
||||
class="text-link"
|
||||
value="&telemetryLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
<groupbox>
|
||||
<caption label="&FHRSection.label;"/>
|
||||
<description>&FHRDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitHealthReportBox"
|
||||
oncommand="gAdvancedPane.updateSubmitHealthReport();"
|
||||
label="&enableFHR.label;"
|
||||
accesskey="&enableFHR.accesskey;"/>
|
||||
<spacer flex="1"/>
|
||||
<label id="FHRLearnMore"
|
||||
class="text-link"
|
||||
value="&FHRLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<groupbox>
|
||||
<caption label="&crashReporterSection.label;"/>
|
||||
<description>&crashReporterDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitCrashesBox"
|
||||
oncommand="gAdvancedPane.updateSubmitCrashes();"
|
||||
label="&enableCrashReporter.label;"
|
||||
accesskey="&enableCrashReporter.accesskey;"/>
|
||||
|
||||
<spacer flex="1"/>
|
||||
<label id="crashReporterLearnMore"
|
||||
class="text-link"
|
||||
value="&crashReporterLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
</tabpanel>
|
||||
#endif
|
||||
<!-- Network -->
|
||||
<tabpanel id="networkPanel" orient="vertical">
|
||||
|
||||
@ -239,11 +288,11 @@
|
||||
<checkbox preference="browser.cache.disk.smart_size.enabled"
|
||||
id="allowSmartSize" flex="1"
|
||||
onsyncfrompreference="return gAdvancedPane.readSmartSizeEnabled();"
|
||||
label="&overrideSmartCacheSize.label;"
|
||||
label="&overrideSmartCacheSize.label;"
|
||||
accesskey="&overrideSmartCacheSize.accesskey;"/>
|
||||
<hbox align="center" class="indent">
|
||||
<label id="useCacheBefore" control="cacheSize"
|
||||
accesskey="&limitCacheSizeBefore.accesskey;"
|
||||
accesskey="&limitCacheSizeBefore.accesskey;"
|
||||
value="&limitCacheSizeBefore.label;"/>
|
||||
<textbox id="cacheSize" type="number" size="4" max="1024"
|
||||
preference="browser.cache.disk.capacity"
|
||||
@ -288,7 +337,7 @@
|
||||
<button id="offlineAppsListRemove"
|
||||
disabled="true"
|
||||
label="&offlineAppsListRemove.label;"
|
||||
accesskey="&offlineAppsListRemove.accesskey;"
|
||||
accesskey="&offlineAppsListRemove.accesskey;"
|
||||
oncommand="gAdvancedPane.removeOfflineApp();"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
@ -389,9 +438,9 @@
|
||||
<radiogroup id="certSelection" orient="horizontal" preftype="string"
|
||||
preference="security.default_personal_cert"
|
||||
aria-labelledby="CertGroupCaption CertSelectionDesc">
|
||||
<radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
|
||||
<radio label="&certs.auto;" accesskey="&certs.auto.accesskey;"
|
||||
value="Select Automatically"/>
|
||||
<radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
|
||||
<radio label="&certs.ask;" accesskey="&certs.ask.accesskey;"
|
||||
value="Ask Every Time"/>
|
||||
</radiogroup>
|
||||
|
||||
@ -402,15 +451,15 @@
|
||||
#endif
|
||||
<hbox>
|
||||
<button id="viewCertificatesButton"
|
||||
label="&viewCerts.label;" accesskey="&viewCerts.accesskey;"
|
||||
label="&viewCerts.label;" accesskey="&viewCerts.accesskey;"
|
||||
oncommand="gAdvancedPane.showCertificates();"
|
||||
preference="security.disable_button.openCertManager"/>
|
||||
<button id="viewCRLButton"
|
||||
label="&viewCRLs.label;" accesskey="&viewCRLs.accesskey;"
|
||||
label="&viewCRLs.label;" accesskey="&viewCRLs.accesskey;"
|
||||
oncommand="gAdvancedPane.showCRLs();"
|
||||
preference="security.OCSP.disable_button.managecrl"/>
|
||||
<button id="verificationButton"
|
||||
label="&verify2.label;" accesskey="&verify2.accesskey;"
|
||||
label="&verify2.label;" accesskey="&verify2.accesskey;"
|
||||
oncommand="gAdvancedPane.showOCSP();"/>
|
||||
#ifdef XP_MACOSX
|
||||
</hbox>
|
||||
|
@ -39,8 +39,9 @@ var gAdvancedPane = {
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
this.initSubmitCrashes();
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
this.initTelemetry();
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
this.initSubmitHealthReport();
|
||||
#endif
|
||||
this.updateActualCacheSize("disk");
|
||||
this.updateActualCacheSize("offline");
|
||||
@ -117,11 +118,45 @@ var gAdvancedPane = {
|
||||
return checkbox.checked ? (this._storedSpellCheck == 2 ? 2 : 1) : 0;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* When the user toggles the layers.acceleration.disabled pref,
|
||||
* sync its new value to the gfx.direct2d.disabled pref too.
|
||||
*/
|
||||
updateHardwareAcceleration: function()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
var fromPref = document.getElementById("layers.acceleration.disabled");
|
||||
var toPref = document.getElementById("gfx.direct2d.disabled");
|
||||
toPref.value = fromPref.value;
|
||||
#endif
|
||||
},
|
||||
|
||||
// DATA CHOICES TAB
|
||||
|
||||
/**
|
||||
* Set up or hide the Learn More links for various data collection options
|
||||
*/
|
||||
_setupLearnMoreLink: function (pref, element) {
|
||||
// set up the Learn More link with the correct URL
|
||||
let url = Services.prefs.getCharPref(pref);
|
||||
let el = document.getElementById(element);
|
||||
|
||||
if (url) {
|
||||
el.setAttribute("href", url);
|
||||
} else {
|
||||
el.setAttribute("hidden", "true");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
initSubmitCrashes: function ()
|
||||
{
|
||||
this._setupLearnMoreLink("toolkit.crashreporter.infoURL",
|
||||
"crashReporterLearnMore");
|
||||
|
||||
var checkbox = document.getElementById("submitCrashesBox");
|
||||
try {
|
||||
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"].
|
||||
@ -145,16 +180,18 @@ var gAdvancedPane = {
|
||||
} catch (e) { }
|
||||
},
|
||||
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
/**
|
||||
* When telemetry is opt-out, verify if the user explicitly rejected the
|
||||
* telemetry prompt, and if so reflect his choice in the current preference
|
||||
* value. This doesn't cover the case where the user refused telemetry in the
|
||||
* prompt but later enabled it in preferences in builds before the fix for
|
||||
* bug 737600.
|
||||
*
|
||||
* In all cases, set up the Learn More link sanely.
|
||||
*/
|
||||
initTelemetry: function ()
|
||||
{
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabledPreRelease";
|
||||
let enabled = Services.prefs.getBoolPref(PREF_TELEMETRY_ENABLED);
|
||||
let rejected = false;
|
||||
@ -164,8 +201,12 @@ var gAdvancedPane = {
|
||||
if (enabled && rejected) {
|
||||
Services.prefs.setBoolPref(PREF_TELEMETRY_ENABLED, false);
|
||||
}
|
||||
},
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
this._setupLearnMoreLink("toolkit.telemetry.infoURL", "telemetryLearnMore");
|
||||
#endif
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* When the user toggles telemetry, update the rejected value as well, so we
|
||||
@ -179,19 +220,46 @@ var gAdvancedPane = {
|
||||
displayed.value = @MOZ_TELEMETRY_DISPLAY_REV@;
|
||||
},
|
||||
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
/**
|
||||
* When the user toggles the layers.acceleration.disabled pref,
|
||||
* sync its new value to the gfx.direct2d.disabled pref too.
|
||||
* Initialize the health report service reference and checkbox.
|
||||
*/
|
||||
updateHardwareAcceleration: function()
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
var fromPref = document.getElementById("layers.acceleration.disabled");
|
||||
var toPref = document.getElementById("gfx.direct2d.disabled");
|
||||
toPref.value = fromPref.value;
|
||||
#endif
|
||||
initSubmitHealthReport: function () {
|
||||
this._setupLearnMoreLink("datareporting.healthreport.infoURL", "FHRLearnMore");
|
||||
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
|
||||
let checkbox = document.getElementById("submitHealthReportBox");
|
||||
|
||||
if (!policy) {
|
||||
checkbox.setAttribute("disabled", "true");
|
||||
return;
|
||||
}
|
||||
|
||||
checkbox.checked = policy.healthReportUploadEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the health report policy acceptance with state from checkbox.
|
||||
*/
|
||||
updateSubmitHealthReport: function () {
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
|
||||
if (!policy) {
|
||||
return;
|
||||
}
|
||||
|
||||
let checkbox = document.getElementById("submitHealthReportBox");
|
||||
policy.healthReportUploadEnabled = checkbox.checked;
|
||||
},
|
||||
#endif
|
||||
|
||||
// NETWORK TAB
|
||||
|
||||
/*
|
||||
|
@ -152,6 +152,9 @@
|
||||
|
||||
<tabs id="tabsElement">
|
||||
<tab id="generalTab" label="&generalTab.label;" helpTopic="prefs-advanced-general"/>
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
<tab id="dataChoicesTab" label="&dataChoicesTab.label;" helpTopic="prefs-advanced-data-choices"/>
|
||||
#endif
|
||||
<tab id="networkTab" label="&networkTab.label;" helpTopic="prefs-advanced-network"/>
|
||||
<tab id="updateTab" label="&updateTab.label;" helpTopic="prefs-advanced-update"/>
|
||||
<tab id="encryptionTab" label="&encryptionTab.label;" helpTopic="prefs-advanced-encryption"/>
|
||||
@ -201,14 +204,14 @@
|
||||
onsynctopreference="return gAdvancedPane.writeCheckSpelling();"
|
||||
preference="layout.spellcheckDefault"/>
|
||||
</groupbox>
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
<!-- System Defaults -->
|
||||
<groupbox id="systemDefaultsGroup" orient="vertical">
|
||||
<caption label="&systemDefaults.label;"/>
|
||||
|
||||
#ifdef HAVE_SHELL_SERVICE
|
||||
<checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
|
||||
label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
|
||||
flex="1"/>
|
||||
label="&alwaysCheckDefault.label;" accesskey="&alwaysCheckDefault.accesskey;"
|
||||
flex="1"/>
|
||||
<hbox class="indent">
|
||||
<deck id="setDefaultPane">
|
||||
<button id="setDefaultButton"
|
||||
@ -218,19 +221,63 @@
|
||||
<description>&isDefault.label;</description>
|
||||
</deck>
|
||||
</hbox>
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<checkbox id="submitCrashesBox" flex="1"
|
||||
oncommand="gAdvancedPane.updateSubmitCrashes();"
|
||||
label="&submitCrashes.label;" accesskey="&submitCrashes.accesskey;"/>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<checkbox id="submitTelemetryBox" flex="1"
|
||||
preference="toolkit.telemetry.enabled"
|
||||
label="&submitTelemetry.label;" accesskey="&submitTelemetry.accesskey;"/>
|
||||
#endif
|
||||
</groupbox>
|
||||
#endif
|
||||
</tabpanel>
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
<!-- Data Choices -->
|
||||
<tabpanel id="dataChoicesPanel" orient="vertical">
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<groupbox>
|
||||
<caption label="&telemetrySection.label;"/>
|
||||
<description>&telemetryDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitTelemetryBox"
|
||||
preference="toolkit.telemetry.enabled"
|
||||
label="&enableTelemetry.label;"
|
||||
accesskey="&enableTelemetry.accesskey;"/>
|
||||
<spacer flex="1"/>
|
||||
<label id="telemetryLearnMore"
|
||||
class="text-link"
|
||||
value="&telemetryLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
<groupbox>
|
||||
<caption label="&FHRSection.label;"/>
|
||||
<description>&FHRDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitHealthReportBox"
|
||||
oncommand="gAdvancedPane.updateSubmitHealthReport();"
|
||||
label="&enableFHR.label;"
|
||||
accesskey="&enableFHR.accesskey;"/>
|
||||
<spacer flex="1"/>
|
||||
<label id="FHRLearnMore"
|
||||
class="text-link"
|
||||
value="&FHRLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
<groupbox>
|
||||
<caption label="&crashReporterSection.label;"/>
|
||||
<description>&crashReporterDesc.label;</description>
|
||||
<hbox>
|
||||
<checkbox id="submitCrashesBox"
|
||||
oncommand="gAdvancedPane.updateSubmitCrashes();"
|
||||
label="&enableCrashReporter.label;"
|
||||
accesskey="&enableCrashReporter.accesskey;"/>
|
||||
|
||||
<spacer flex="1"/>
|
||||
<label id="crashReporterLearnMore"
|
||||
class="text-link"
|
||||
value="&crashReporterLearnMore.label;"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
</tabpanel>
|
||||
#endif
|
||||
|
||||
<!-- Network -->
|
||||
<tabpanel id="networkPanel" orient="vertical">
|
||||
|
@ -43,5 +43,9 @@ _BROWSER_FILES += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
_BROWSER_FILES += browser_healthreport.js
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -0,0 +1,48 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
resetPreferences();
|
||||
registerCleanupFunction(resetPreferences);
|
||||
open_preferences(runTest);
|
||||
}
|
||||
|
||||
function runTest(win) {
|
||||
let doc = win.document;
|
||||
|
||||
win.gotoPref("paneAdvanced");
|
||||
let advancedPrefs = doc.getElementById("advancedPrefs");
|
||||
let dataChoicesTab = doc.getElementById("dataChoicesTab");
|
||||
advancedPrefs.selectedTab = dataChoicesTab;
|
||||
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
ok(policy);
|
||||
is(policy.dataSubmissionPolicyAccepted, false, "Data submission policy not accepted.");
|
||||
is(policy.healthReportUploadEnabled, true, "Health Report upload enabled on app first run.");
|
||||
|
||||
let checkbox = doc.getElementById("submitHealthReportBox");
|
||||
ok(checkbox);
|
||||
is(checkbox.checked, true, "Health Report checkbox is checked on app first run.");
|
||||
|
||||
checkbox.checked = false;
|
||||
checkbox.doCommand();
|
||||
is(policy.healthReportUploadEnabled, false, "Unchecking checkbox opts out of FHR upload.");
|
||||
|
||||
checkbox.checked = true;
|
||||
checkbox.doCommand();
|
||||
is(policy.healthReportUploadEnabled, true, "Checking checkbox allows FHR upload.");
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
function resetPreferences() {
|
||||
Services.prefs.clearUserPref("datareporting.healthreport.uploadEnabled");
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ function is_element_hidden(aElement, aMsg) {
|
||||
function open_preferences(aCallback) {
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:preferences");
|
||||
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
newTabBrowser.addEventListener("load", function () {
|
||||
newTabBrowser.removeEventListener("load", arguments.callee, true);
|
||||
newTabBrowser.addEventListener("Initialized", function () {
|
||||
newTabBrowser.removeEventListener("Initialized", arguments.callee, true);
|
||||
aCallback(gBrowser.contentWindow);
|
||||
}, true);
|
||||
}
|
||||
|
@ -43,5 +43,9 @@ _BROWSER_FILES += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
_BROWSER_FILES += browser_healthreport.js
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
50
browser/components/preferences/tests/browser_healthreport.js
Normal file
50
browser/components/preferences/tests/browser_healthreport.js
Normal file
@ -0,0 +1,50 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
resetPreferences();
|
||||
registerCleanupFunction(resetPreferences);
|
||||
|
||||
function observer(win, topic, data) {
|
||||
Services.obs.removeObserver(observer, "advanced-pane-loaded");
|
||||
runTest(win);
|
||||
}
|
||||
Services.obs.addObserver(observer, "advanced-pane-loaded", false);
|
||||
openDialog("chrome://browser/content/preferences/preferences.xul", "Preferences",
|
||||
"chrome,titlebar,toolbar,centerscreen,dialog=no", "paneAdvanced");
|
||||
}
|
||||
|
||||
function runTest(win) {
|
||||
let doc = win.document;
|
||||
|
||||
let policy = Components.classes["@mozilla.org/datareporting/service;1"]
|
||||
.getService(Components.interfaces.nsISupports)
|
||||
.wrappedJSObject
|
||||
.policy;
|
||||
ok(policy);
|
||||
is(policy.dataSubmissionPolicyAccepted, false, "Data submission policy not accepted.");
|
||||
is(policy.healthReportUploadEnabled, true, "Health Report upload enabled on app first run.");
|
||||
|
||||
let checkbox = doc.getElementById("submitHealthReportBox");
|
||||
ok(checkbox);
|
||||
is(checkbox.checked, true, "Health Report checkbox is checked on app first run.");
|
||||
|
||||
checkbox.checked = false;
|
||||
checkbox.doCommand();
|
||||
is(policy.healthReportUploadEnabled, false, "Unchecking checkbox opts out of FHR upload.");
|
||||
|
||||
checkbox.checked = true;
|
||||
checkbox.doCommand();
|
||||
is(policy.healthReportUploadEnabled, true, "Checking checkbox allows FHR upload.");
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
function resetPreferences() {
|
||||
Services.prefs.clearUserPref("datareporting.healthreport.uploadEnabled");
|
||||
}
|
||||
|
@ -28,6 +28,11 @@ MOZ_SAFE_BROWSING=1
|
||||
MOZ_SERVICES_AITC=1
|
||||
MOZ_SERVICES_COMMON=1
|
||||
MOZ_SERVICES_CRYPTO=1
|
||||
|
||||
if test "$OS_ARCH" != "Linux"; then
|
||||
MOZ_SERVICES_HEALTHREPORT=1
|
||||
fi
|
||||
|
||||
MOZ_SERVICES_METRICS=1
|
||||
MOZ_SERVICES_SYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
|
@ -469,9 +469,9 @@
|
||||
@BINPATH@/components/AitcComponents.manifest
|
||||
@BINPATH@/components/Aitc.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
@BINPATH@/components/HealthReportComponents.manifest
|
||||
@BINPATH@/components/HealthReportService.js
|
||||
#ifdef MOZ_DATA_REPORTING
|
||||
@BINPATH@/components/DataReporting.manifest
|
||||
@BINPATH@/components/DataReportingService.js
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
@BINPATH@/components/SyncComponents.manifest
|
||||
|
@ -899,6 +899,7 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/GPSDGeolocationProvider.js
|
||||
components/interfaces.manifest
|
||||
components/jsconsole-clhandler.js
|
||||
components/MetricsCollectionService.js
|
||||
components/NetworkGeolocationProvider.js
|
||||
components/NotificationsComponents.manifest
|
||||
components/nsBadCertHandler.js
|
||||
|
27
browser/locales/en-US/chrome/browser/aboutHealthReport.dtd
Normal file
27
browser/locales/en-US/chrome/browser/aboutHealthReport.dtd
Normal file
@ -0,0 +1,27 @@
|
||||
<!-- metrics.locale-direction instead of the usual local.dir entity, so RTL can skip translating page. -->
|
||||
<!ENTITY abouthealth.locale-direction "ltr">
|
||||
|
||||
<!-- LOCALIZATION NOTE (abouthealth.pagetitle): Firefox Health Report is a proper noun in en-US, please keep this in mind. -->
|
||||
<!ENTITY abouthealth.pagetitle "&brandShortName; Health Report">
|
||||
<!ENTITY abouthealth.header "&brandFullName; Health Report">
|
||||
|
||||
<!ENTITY abouthealth.intro.title "What is &brandShortName; Health Report?">
|
||||
|
||||
<!ENTITY abouthealth.intro-enabled "&brandFullName; collects some data about your computer and usage in order to provide you with a better browser experience.">
|
||||
<!ENTITY abouthealth.intro-disabled "You are currently not submitting usage data to &vendorShortName;. You can help us make &brandShortName; better by clicking the "&abouthealth.optin;" button.">
|
||||
|
||||
<!ENTITY abouthealth.optin "Help make &brandShortName; better">
|
||||
<!ENTITY abouthealth.optout "Turn Off Reporting">
|
||||
|
||||
<!ENTITY abouthealth.optout.confirmationPrompt.title "Stop data submission?">
|
||||
<!ENTITY abouthealth.optout.confirmationPrompt.message "Are you sure you want to opt out and delete all your anonymous product data stored on &vendorShortName; servers?">
|
||||
|
||||
<!ENTITY abouthealth.show-raw-data "Show Details">
|
||||
<!ENTITY abouthealth.hide-raw-data "Hide Details">
|
||||
|
||||
<!ENTITY abouthealth.show-report "Show &brandShortName; Report">
|
||||
|
||||
<!ENTITY abouthealth.details.description-start "This is the data &brandFullName; is submitting in order for &brandShortName; Health Report to function. You can ">
|
||||
<!ENTITY abouthealth.details-link "learn more">
|
||||
<!ENTITY abouthealth.details.description-end " about what we collect and submit.">
|
||||
<!ENTITY abouthealth.no-data-available "There is no previous submission to display. Please check back later.">
|
@ -22,6 +22,9 @@
|
||||
<!ENTITY helpSafeMode.label "Restart with Add-ons Disabled…">
|
||||
<!ENTITY helpSafeMode.accesskey "R">
|
||||
|
||||
<!ENTITY healthReport.label "&brandShortName; Health Report">
|
||||
<!ENTITY healthReport.accesskey "e">
|
||||
|
||||
<!ENTITY helpTroubleshootingInfo.label "Troubleshooting Information">
|
||||
<!ENTITY helpTroubleshootingInfo.accesskey "T">
|
||||
|
||||
|
@ -351,16 +351,10 @@ syncPromoNotification.addons.description=You can access your add-ons on all your
|
||||
# The final space separates this text from the Learn More link.
|
||||
syncPromoNotification.addons-sync-disabled.description=You can use your %S account to synchronize add-ons across multiple devices.\u0020
|
||||
|
||||
# Telemetry prompt
|
||||
# LOCALIZATION NOTE (telemetryOptInPrompt): %1$S will be replaced by
|
||||
# brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner
|
||||
# preference.
|
||||
telemetryOptInPrompt = Will you help improve %1$S by sending information about performance, hardware, usage, and customizations to %2$S?
|
||||
telemetryLinkLabel = Learn More
|
||||
telemetryYesButtonLabel2 = Yes, I want to help
|
||||
telemetryYesButtonAccessKey = Y
|
||||
telemetryNoButtonLabel = No
|
||||
telemetryNoButtonAccessKey = N
|
||||
# Mozilla data reporting notification (Telemetry, Firefox Health Report, etc)
|
||||
dataReportingNotification.message = %1$S automatically sends some data to %2$S so that we can improve your experience.
|
||||
dataReportingNotification.button.label = Choose What I Share
|
||||
dataReportingNotification.button.accessKey = C
|
||||
|
||||
# Keyword.URL reset prompt
|
||||
# LOCALIZATION NOTE (keywordPrompt.message):
|
||||
@ -384,11 +378,6 @@ webapps.install.accesskey = I
|
||||
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
|
||||
webapps.install.success = Application Installed
|
||||
|
||||
# Telemetry opt-out prompt for Aurora and Nightly
|
||||
# LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
|
||||
# brandShortName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
|
||||
telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
|
||||
|
||||
# LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
|
||||
fullscreen.entered=%S is now fullscreen.
|
||||
# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
|
||||
|
@ -32,10 +32,26 @@
|
||||
<!ENTITY setDefault.label "Make &brandShortName; the default browser">
|
||||
<!ENTITY setDefault.accesskey "d">
|
||||
<!ENTITY isDefault.label "&brandShortName; is currently your default browser">
|
||||
<!ENTITY submitCrashes.label "Submit crash reports">
|
||||
<!ENTITY submitCrashes.accesskey "S">
|
||||
<!ENTITY submitTelemetry.label "Submit performance data">
|
||||
<!ENTITY submitTelemetry.accesskey "P">
|
||||
|
||||
<!ENTITY dataChoicesTab.label "Data Choices">
|
||||
|
||||
<!ENTITY FHRSection.label "Firefox Health Report">
|
||||
<!ENTITY FHRDesc.label "Helps you understand your browser performance and shares data with &vendorShortName; about your browser health">
|
||||
<!ENTITY enableFHR.label "Enable Firefox Health Report">
|
||||
<!ENTITY enableFHR.accesskey "F">
|
||||
<!ENTITY FHRLearnMore.label "Learn More">
|
||||
|
||||
<!ENTITY telemetrySection.label "Telemetry">
|
||||
<!ENTITY telemetryDesc.label "Shares performance, usage, hardware and customization data about your browser with &vendorShortName; to help us make &brandShortName; better">
|
||||
<!ENTITY enableTelemetry.label "Enable Telemetry">
|
||||
<!ENTITY enableTelemetry.accesskey "T">
|
||||
<!ENTITY telemetryLearnMore.label "Learn More">
|
||||
|
||||
<!ENTITY crashReporterSection.label "Crash Reporter">
|
||||
<!ENTITY crashReporterDesc.label "&brandShortName; submits crash reports to help &vendorShortName; make your browser more stable and secure">
|
||||
<!ENTITY enableCrashReporter.label "Enable Crash Reporter">
|
||||
<!ENTITY enableCrashReporter.accesskey "C">
|
||||
<!ENTITY crashReporterLearnMore.label "Learn More">
|
||||
|
||||
<!ENTITY networkTab.label "Network">
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
locale/browser/aboutPrivateBrowsing.dtd (%chrome/browser/aboutPrivateBrowsing.dtd)
|
||||
locale/browser/aboutRobots.dtd (%chrome/browser/aboutRobots.dtd)
|
||||
locale/browser/aboutHome.dtd (%chrome/browser/aboutHome.dtd)
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
locale/browser/aboutHealthReport.dtd (%chrome/browser/aboutHealthReport.dtd)
|
||||
#endif
|
||||
locale/browser/aboutSessionRestore.dtd (%chrome/browser/aboutSessionRestore.dtd)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
locale/browser/syncProgress.dtd (%chrome/browser/syncProgress.dtd)
|
||||
|
@ -460,6 +460,9 @@ user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_com
|
||||
|
||||
// Get network events.
|
||||
user_pref("network.activity.blipIntervalMilliseconds", 250);
|
||||
|
||||
// Don't allow the Data Reporting service to prompt for policy acceptance.
|
||||
user_pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", true);
|
||||
""" % { "server" : self.webServer + ":" + str(self.httpPort) }
|
||||
prefs.append(part)
|
||||
|
||||
|
@ -8719,6 +8719,15 @@ if test "$MOZ_TELEMETRY_REPORTING"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl If we have any service that uploads data (and requires data submission
|
||||
dnl policy alert), set MOZ_DATA_REPORTING.
|
||||
dnl We need SUBST for build system and DEFINE for xul preprocessor.
|
||||
if test -n "$MOZ_TELEMETRY_REPORTING" || test -n "$MOZ_SERVICES_HEALTHREPORT" || test -n "MOZ_CRASHREPORTER"; then
|
||||
MOZ_DATA_REPORTING=1
|
||||
AC_DEFINE(MOZ_DATA_REPORTING)
|
||||
AC_SUBST(MOZ_DATA_REPORTING)
|
||||
fi
|
||||
|
||||
dnl win32 options
|
||||
AC_SUBST(MOZ_MAPINFO)
|
||||
AC_SUBST(MOZ_BROWSE_INFO)
|
||||
|
@ -324,6 +324,7 @@ user_pref("reftest.remote", true);
|
||||
user_pref("toolkit.telemetry.prompted", 999);
|
||||
user_pref("toolkit.telemetry.notifiedOptOut", 999);
|
||||
user_pref("reftest.uri", "%s");
|
||||
user_pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", true);
|
||||
""" % reftestlist)
|
||||
|
||||
#workaround for jsreftests.
|
||||
|
@ -43,6 +43,10 @@ GARBAGE += greprefs.js
|
||||
# TODO bug 813259 external files should be defined near their location in the source tree.
|
||||
grepref_files = $(topsrcdir)/netwerk/base/public/security-prefs.js $(srcdir)/init/all.js
|
||||
|
||||
ifdef MOZ_DATA_REPORTING
|
||||
grepref_files += $(topsrcdir)/services/datareporting/datareporting-prefs.js
|
||||
endif
|
||||
|
||||
ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
grepref_files += $(topsrcdir)/services/healthreport/healthreport-prefs.js
|
||||
endif
|
||||
|
@ -9,9 +9,10 @@ VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
PARALLEL_DIRS += common
|
||||
|
||||
PARALLEL_DIRS += crypto
|
||||
PARALLEL_DIRS += \
|
||||
common \
|
||||
crypto \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_SERVICES_AITC
|
||||
PARALLEL_DIRS += aitc
|
||||
@ -21,6 +22,10 @@ ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
PARALLEL_DIRS += healthreport
|
||||
endif
|
||||
|
||||
ifdef MOZ_DATA_REPORTING
|
||||
PARALLEL_DIRS += datareporting
|
||||
endif
|
||||
|
||||
ifdef MOZ_SERVICES_METRICS
|
||||
PARALLEL_DIRS += metrics
|
||||
endif
|
||||
|
16
services/datareporting/DataReporting.manifest
Normal file
16
services/datareporting/DataReporting.manifest
Normal file
@ -0,0 +1,16 @@
|
||||
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
|
||||
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
|
||||
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
|
||||
# suite (comm): {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
|
||||
# metro browser: {99bceaaa-e3c6-48c1-b981-ef9b46b67d60}
|
||||
|
||||
# The Data Reporting Service drives collection and submission of metrics
|
||||
# and other useful data to Mozilla. It drives the display of the data
|
||||
# submission notification info bar and thus is required by Firefox Health
|
||||
# Report and Telemetry.
|
||||
|
||||
component {41f6ae36-a79f-4613-9ac3-915e70f83789} DataReportingService.js
|
||||
contract @mozilla.org/datareporting/service;1 {41f6ae36-a79f-4613-9ac3-915e70f83789}
|
||||
category app-startup DataReportingService service,@mozilla.org/datareporting/service;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
|
||||
|
@ -6,11 +6,16 @@
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://services-common/observers.js");
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
|
||||
|
||||
const BRANCH = "healthreport.";
|
||||
const ROOT_BRANCH = "datareporting.";
|
||||
const POLICY_BRANCH = ROOT_BRANCH + "policy.";
|
||||
const HEALTHREPORT_BRANCH = ROOT_BRANCH + "healthreport.";
|
||||
const HEALTHREPORT_LOGGING_BRANCH = HEALTHREPORT_BRANCH + "logging.";
|
||||
const DEFAULT_LOAD_DELAY_MSEC = 10 * 1000;
|
||||
|
||||
/**
|
||||
@ -27,7 +32,7 @@ const DEFAULT_LOAD_DELAY_MSEC = 10 * 1000;
|
||||
* let reporter = Cc["@mozilla.org/healthreport/service;1"]
|
||||
* .getService(Ci.nsISupports)
|
||||
* .wrappedJSObject
|
||||
* .reporter;
|
||||
* .healthReporter;
|
||||
*
|
||||
* if (reporter.haveRemoteData) {
|
||||
* // ...
|
||||
@ -45,36 +50,77 @@ const DEFAULT_LOAD_DELAY_MSEC = 10 * 1000;
|
||||
* instance (it registers observers on initialization). See the notes on that
|
||||
* type for more.
|
||||
*/
|
||||
this.HealthReportService = function HealthReportService() {
|
||||
this.DataReportingService = function () {
|
||||
this.wrappedJSObject = this;
|
||||
|
||||
this._prefs = new Preferences(BRANCH);
|
||||
|
||||
this._reporter = null;
|
||||
this._os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
}
|
||||
|
||||
HealthReportService.prototype = {
|
||||
classID: Components.ID("{e354c59b-b252-4040-b6dd-b71864e3e35c}"),
|
||||
DataReportingService.prototype = Object.freeze({
|
||||
classID: Components.ID("{41f6ae36-a79f-4613-9ac3-915e70f83789}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
// If the background service is disabled, don't do anything.
|
||||
if (!this._prefs.get("service.enabled", true)) {
|
||||
//---------------------------------------------
|
||||
// Start of policy listeners.
|
||||
//---------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when policy requests data upload.
|
||||
*/
|
||||
onRequestDataUpload: function (request) {
|
||||
if (!this.healthReporter) {
|
||||
return;
|
||||
}
|
||||
|
||||
let os = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
this.healthReporter.requestDataUpload(request);
|
||||
},
|
||||
|
||||
onNotifyDataPolicy: function (request) {
|
||||
Observers.notify("datareporting:notify-data-policy:request", request);
|
||||
},
|
||||
|
||||
onRequestRemoteDelete: function (request) {
|
||||
if (!this.healthReporter) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.healthReporter.deleteRemoteData(request);
|
||||
},
|
||||
|
||||
//---------------------------------------------
|
||||
// End of policy listeners.
|
||||
//---------------------------------------------
|
||||
|
||||
observe: function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "app-startup":
|
||||
os.addObserver(this, "final-ui-startup", true);
|
||||
this._os.addObserver(this, "profile-after-change", true);
|
||||
break;
|
||||
|
||||
case "final-ui-startup":
|
||||
os.removeObserver(this, "final-ui-startup");
|
||||
case "profile-after-change":
|
||||
this._os.removeObserver(this, "profile-after-change");
|
||||
this._os.addObserver(this, "sessionstore-windows-restored", true);
|
||||
|
||||
// We can't interact with prefs until after the profile is present.
|
||||
let policyPrefs = new Preferences(POLICY_BRANCH);
|
||||
this._prefs = new Preferences(HEALTHREPORT_BRANCH);
|
||||
this.policy = new DataReportingPolicy(policyPrefs, this._prefs, this);
|
||||
break;
|
||||
|
||||
case "sessionstore-windows-restored":
|
||||
this._os.removeObserver(this, "sessionstore-windows-restored");
|
||||
this._os.addObserver(this, "quit-application", false);
|
||||
|
||||
this.policy.startPolling();
|
||||
|
||||
// Don't initialize Firefox Health Reporter collection and submission
|
||||
// service unless it is enabled.
|
||||
if (!this._prefs.get("service.enabled", true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let delayInterval = this._prefs.get("service.loadDelayMsec") ||
|
||||
DEFAULT_LOAD_DELAY_MSEC;
|
||||
@ -86,12 +132,17 @@ HealthReportService.prototype = {
|
||||
notify: function notify() {
|
||||
// Side effect: instantiates the reporter instance if not already
|
||||
// accessed.
|
||||
let reporter = this.reporter;
|
||||
let reporter = this.healthReporter;
|
||||
delete this.timer;
|
||||
}.bind(this),
|
||||
}, delayInterval, this.timer.TYPE_ONE_SHOT);
|
||||
|
||||
break;
|
||||
|
||||
case "quit-application":
|
||||
this._os.removeObserver(this, "quit-application");
|
||||
this.policy.stopPolling();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -102,17 +153,28 @@ HealthReportService.prototype = {
|
||||
*
|
||||
* The obtained instance may not be fully initialized.
|
||||
*/
|
||||
get reporter() {
|
||||
get healthReporter() {
|
||||
if (!this._prefs.get("service.enabled", true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._reporter) {
|
||||
return this._reporter;
|
||||
if ("_healthReporter" in this) {
|
||||
return this._healthReporter;
|
||||
}
|
||||
|
||||
try {
|
||||
this._loadHealthReporter();
|
||||
} catch (ex) {
|
||||
this._healthReporter = null;
|
||||
}
|
||||
|
||||
return this._healthReporter;
|
||||
},
|
||||
|
||||
_loadHealthReporter: function () {
|
||||
let ns = {};
|
||||
// Lazy import so application startup isn't adversely affected.
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm", ns);
|
||||
Cu.import("resource://gre/modules/services/healthreport/healthreporter.jsm", ns);
|
||||
Cu.import("resource://services-common/log4moz.js", ns);
|
||||
@ -120,15 +182,16 @@ HealthReportService.prototype = {
|
||||
// How many times will we rewrite this code before rolling it up into a
|
||||
// generic module? See also bug 451283.
|
||||
const LOGGERS = [
|
||||
"Services.DataReporting",
|
||||
"Services.HealthReport",
|
||||
"Services.Metrics",
|
||||
"Services.BagheeraClient",
|
||||
"Sqlite.Connection.healthreport",
|
||||
];
|
||||
|
||||
let prefs = new Preferences(BRANCH + "logging.");
|
||||
if (prefs.get("consoleEnabled", true)) {
|
||||
let level = prefs.get("consoleLevel", "Warn");
|
||||
let loggingPrefs = new Preferences(HEALTHREPORT_LOGGING_BRANCH);
|
||||
if (loggingPrefs.get("consoleEnabled", true)) {
|
||||
let level = loggingPrefs.get("consoleLevel", "Warn");
|
||||
let appender = new ns.Log4Moz.ConsoleAppender();
|
||||
appender.level = ns.Log4Moz.Level[level] || ns.Log4Moz.Level.Warn;
|
||||
|
||||
@ -139,13 +202,10 @@ HealthReportService.prototype = {
|
||||
}
|
||||
|
||||
// The reporter initializes in the background.
|
||||
this._reporter = new ns.HealthReporter(BRANCH);
|
||||
|
||||
return this._reporter;
|
||||
this._healthReporter = new ns.HealthReporter(HEALTHREPORT_BRANCH,
|
||||
this.policy);
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
Object.freeze(HealthReportService.prototype);
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HealthReportService]);
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataReportingService]);
|
||||
|
26
services/datareporting/Makefile.in
Normal file
26
services/datareporting/Makefile.in
Normal file
@ -0,0 +1,26 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
TEST_DIRS += tests
|
||||
|
||||
MODULES_FILES := policy.jsm
|
||||
MODULES_DEST = $(FINAL_TARGET)/modules/services/datareporting
|
||||
INSTALL_TARGETS += MODULES
|
||||
|
||||
TESTING_JS_MODULES := $(addprefix modules-testing/,mocks.jsm)
|
||||
TESTING_JS_MODULE_DIR := services/datareporting
|
||||
|
||||
EXTRA_COMPONENTS := \
|
||||
DataReporting.manifest \
|
||||
DataReportingService.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
12
services/datareporting/datareporting-prefs.js
Normal file
12
services/datareporting/datareporting-prefs.js
Normal file
@ -0,0 +1,12 @@
|
||||
/* 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/. */
|
||||
|
||||
pref("datareporting.policy.dataSubmissionEnabled", true);
|
||||
pref("datareporting.policy.dataSubmissionPolicyAccepted", false);
|
||||
pref("datareporting.policy.dataSubmissionPolicyBypassAcceptance", false);
|
||||
pref("datareporting.policy.dataSubmissionPolicyNotifiedTime", "0");
|
||||
pref("datareporting.policy.dataSubmissionPolicyResponseType", "");
|
||||
pref("datareporting.policy.dataSubmissionPolicyResponseTime", "0");
|
||||
pref("datareporting.policy.firstRunTime", "0");
|
||||
|
@ -12,7 +12,7 @@ Cu.import("resource://services-common/log4moz.js");
|
||||
|
||||
|
||||
this.MockPolicyListener = function MockPolicyListener() {
|
||||
this._log = Log4Moz.repository.getLogger("HealthReport.Testing.MockPolicyListener");
|
||||
this._log = Log4Moz.repository.getLogger("Services.DataReporting.Testing.MockPolicyListener");
|
||||
this._log.level = Log4Moz.Level["Debug"];
|
||||
|
||||
this.requestDataUploadCount = 0;
|
||||
@ -44,3 +44,4 @@ MockPolicyListener.prototype = {
|
||||
this.lastNotifyRequest = request;
|
||||
},
|
||||
};
|
||||
|
@ -2,11 +2,22 @@
|
||||
* 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 file is in transition. It was originally conceived to fulfill the
|
||||
* needs of only Firefox Health Report. It is slowly being morphed into
|
||||
* fulfilling the needs of all data reporting facilities in Gecko applications.
|
||||
* As a result, some things feel a bit weird.
|
||||
*
|
||||
* DataReportingPolicy is both a driver for data reporting notification
|
||||
* (a true policy) and the driver for FHR data submission. The latter should
|
||||
* eventually be split into its own type and module.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"DataSubmissionRequest", // For test use only.
|
||||
"HealthReportPolicy",
|
||||
"DataReportingPolicy",
|
||||
];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
@ -41,7 +52,7 @@ const OLDEST_ALLOWED_YEAR = 2012;
|
||||
* signaling explicit user acceptance or rejection of the policy. They do this
|
||||
* by calling `onUserAccept` or `onUserReject`, respectively. These functions
|
||||
* are essentially proxies to
|
||||
* HealthReportPolicy.{recordUserAcceptance,recordUserRejection}.
|
||||
* DataReportingPolicy.{recordUserAcceptance,recordUserRejection}.
|
||||
*
|
||||
* If the user never explicitly accepts or rejects the policy, it will be
|
||||
* implicitly accepted after a specified duration of time. The notice is
|
||||
@ -53,7 +64,7 @@ const OLDEST_ALLOWED_YEAR = 2012;
|
||||
* the exception of the on* functions.
|
||||
*
|
||||
* @param policy
|
||||
* (HealthReportPolicy) The policy instance this request came from.
|
||||
* (DataReportingPolicy) The policy instance this request came from.
|
||||
* @param promise
|
||||
* (deferred) The promise that will be fulfilled when display occurs.
|
||||
*/
|
||||
@ -235,15 +246,17 @@ Object.freeze(DataSubmissionRequest.prototype);
|
||||
* can have different mechanisms by which they notify the user of data
|
||||
* submission practices.
|
||||
*
|
||||
* @param prefs
|
||||
* @param policyPrefs
|
||||
* (Preferences) Handle on preferences branch on which state will be
|
||||
* queried and stored.
|
||||
* @param healthReportPrefs
|
||||
* (Preferences) Handle on preferences branch hold Health Report state.
|
||||
* @param listener
|
||||
* (object) Object with callbacks that will be invoked at certain key
|
||||
* events.
|
||||
*/
|
||||
this.HealthReportPolicy = function HealthReportPolicy(prefs, listener) {
|
||||
this._log = Log4Moz.repository.getLogger("Services.HealthReport.Policy");
|
||||
this.DataReportingPolicy = function (prefs, healthReportPrefs, listener) {
|
||||
this._log = Log4Moz.repository.getLogger("Services.DataReporting.Policy");
|
||||
this._log.level = Log4Moz.Level["Debug"];
|
||||
|
||||
for (let handler of this.REQUIRED_LISTENERS) {
|
||||
@ -254,6 +267,7 @@ this.HealthReportPolicy = function HealthReportPolicy(prefs, listener) {
|
||||
}
|
||||
|
||||
this._prefs = prefs;
|
||||
this._healthReportPrefs = healthReportPrefs;
|
||||
this._listener = listener;
|
||||
|
||||
// If we've never run before, record the current time.
|
||||
@ -276,7 +290,7 @@ this.HealthReportPolicy = function HealthReportPolicy(prefs, listener) {
|
||||
this._inProgressSubmissionRequest = null;
|
||||
}
|
||||
|
||||
HealthReportPolicy.prototype = {
|
||||
DataReportingPolicy.prototype = Object.freeze({
|
||||
/**
|
||||
* How long after first run we should notify about data submission.
|
||||
*/
|
||||
@ -444,22 +458,6 @@ HealthReportPolicy.prototype = {
|
||||
this._prefs.set("dataSubmissionEnabled", !!value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether upload of data is allowed.
|
||||
*
|
||||
* This is a kill switch for upload. It is meant to reflect a system or
|
||||
* deployment policy decision. User intent should be reflected in the
|
||||
* "dataSubmissionPolicy" prefs.
|
||||
*/
|
||||
get dataUploadEnabled() {
|
||||
// Default is true because we are opt-out.
|
||||
return this._prefs.get("dataUploadEnabled", true);
|
||||
},
|
||||
|
||||
set dataUploadEnabled(value) {
|
||||
this._prefs.set("dataUploadEnabled", !!value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the user has accepted that data submission can occur.
|
||||
*
|
||||
@ -474,13 +472,17 @@ HealthReportPolicy.prototype = {
|
||||
this._prefs.set("dataSubmissionPolicyAccepted", !!value);
|
||||
},
|
||||
|
||||
set dataSubmissionPolicyAcceptedVersion(value) {
|
||||
this._prefs.set("dataSubmissionPolicyAcceptedVersion", value);
|
||||
},
|
||||
|
||||
/**
|
||||
* The state of user notification of the data policy.
|
||||
*
|
||||
* This must be HealthReportPolicy.STATE_NOTIFY_COMPLETE before data
|
||||
* This must be DataReportingPolicy.STATE_NOTIFY_COMPLETE before data
|
||||
* submission can occur.
|
||||
*
|
||||
* @return HealthReportPolicy.STATE_NOTIFY_* constant.
|
||||
* @return DataReportingPolicy.STATE_NOTIFY_* constant.
|
||||
*/
|
||||
get notifyState() {
|
||||
if (this.dataSubmissionPolicyResponseDate.getTime()) {
|
||||
@ -505,13 +507,14 @@ HealthReportPolicy.prototype = {
|
||||
* on scheduling or run-time behavior.
|
||||
*/
|
||||
get lastDataSubmissionRequestedDate() {
|
||||
return CommonUtils.getDatePref(this._prefs,
|
||||
return CommonUtils.getDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionRequestedTime", 0,
|
||||
this._log, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
set lastDataSubmissionRequestedDate(value) {
|
||||
CommonUtils.setDatePref(this._prefs, "lastDataSubmissionRequestedTime",
|
||||
CommonUtils.setDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionRequestedTime",
|
||||
value, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
@ -522,13 +525,14 @@ HealthReportPolicy.prototype = {
|
||||
* actual scheduling.
|
||||
*/
|
||||
get lastDataSubmissionSuccessfulDate() {
|
||||
return CommonUtils.getDatePref(this._prefs,
|
||||
return CommonUtils.getDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionSuccessfulTime", 0,
|
||||
this._log, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
set lastDataSubmissionSuccessfulDate(value) {
|
||||
CommonUtils.setDatePref(this._prefs, "lastDataSubmissionSuccessfulTime",
|
||||
CommonUtils.setDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionSuccessfulTime",
|
||||
value, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
@ -539,13 +543,15 @@ HealthReportPolicy.prototype = {
|
||||
* scheduling.
|
||||
*/
|
||||
get lastDataSubmissionFailureDate() {
|
||||
return CommonUtils.getDatePref(this._prefs, "lastDataSubmissionFailureTime",
|
||||
return CommonUtils.getDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionFailureTime",
|
||||
0, this._log, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
set lastDataSubmissionFailureDate(value) {
|
||||
CommonUtils.setDatePref(this._prefs, "lastDataSubmissionFailureTime", value,
|
||||
OLDEST_ALLOWED_YEAR);
|
||||
CommonUtils.setDatePref(this._healthReportPrefs,
|
||||
"lastDataSubmissionFailureTime",
|
||||
value, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -555,12 +561,14 @@ HealthReportPolicy.prototype = {
|
||||
* mutate this value.
|
||||
*/
|
||||
get nextDataSubmissionDate() {
|
||||
return CommonUtils.getDatePref(this._prefs, "nextDataSubmissionTime", 0,
|
||||
return CommonUtils.getDatePref(this._healthReportPrefs,
|
||||
"nextDataSubmissionTime", 0,
|
||||
this._log, OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
set nextDataSubmissionDate(value) {
|
||||
CommonUtils.setDatePref(this._prefs, "nextDataSubmissionTime", value,
|
||||
CommonUtils.setDatePref(this._healthReportPrefs,
|
||||
"nextDataSubmissionTime", value,
|
||||
OLDEST_ALLOWED_YEAR);
|
||||
},
|
||||
|
||||
@ -570,7 +578,7 @@ HealthReportPolicy.prototype = {
|
||||
* This is used to drive backoff and scheduling.
|
||||
*/
|
||||
get currentDaySubmissionFailureCount() {
|
||||
let v = this._prefs.get("currentDaySubmissionFailureCount", 0);
|
||||
let v = this._healthReportPrefs.get("currentDaySubmissionFailureCount", 0);
|
||||
|
||||
if (!Number.isInteger(v)) {
|
||||
v = 0;
|
||||
@ -584,7 +592,7 @@ HealthReportPolicy.prototype = {
|
||||
throw new Error("Value must be integer: " + value);
|
||||
}
|
||||
|
||||
this._prefs.set("currentDaySubmissionFailureCount", value);
|
||||
this._healthReportPrefs.set("currentDaySubmissionFailureCount", value);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -595,11 +603,22 @@ HealthReportPolicy.prototype = {
|
||||
* the remote deletion is fulfilled.
|
||||
*/
|
||||
get pendingDeleteRemoteData() {
|
||||
return !!this._prefs.get("pendingDeleteRemoteData", false);
|
||||
return !!this._healthReportPrefs.get("pendingDeleteRemoteData", false);
|
||||
},
|
||||
|
||||
set pendingDeleteRemoteData(value) {
|
||||
this._prefs.set("pendingDeleteRemoteData", !!value);
|
||||
this._healthReportPrefs.set("pendingDeleteRemoteData", !!value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether upload of Firefox Health Report data is enabled.
|
||||
*/
|
||||
get healthReportUploadEnabled() {
|
||||
return !!this._healthReportPrefs.get("uploadEnabled", true);
|
||||
},
|
||||
|
||||
set healthReportUploadEnabled(value) {
|
||||
this._healthReportPrefs.set("uploadEnabled", !!value);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -620,6 +639,7 @@ HealthReportPolicy.prototype = {
|
||||
this.dataSubmissionPolicyResponseDate = this.now();
|
||||
this.dataSubmissionPolicyResponseType = "accepted-" + reason;
|
||||
this.dataSubmissionPolicyAccepted = true;
|
||||
this.dataSubmissionPolicyAcceptedVersion = 1;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -753,7 +773,7 @@ HealthReportPolicy.prototype = {
|
||||
return this._dispatchSubmissionRequest("onRequestRemoteDelete", true);
|
||||
}
|
||||
|
||||
if (!this.dataUploadEnabled) {
|
||||
if (!this.healthReportUploadEnabled) {
|
||||
this._log.debug("Data upload is disabled. Doing nothing.");
|
||||
return;
|
||||
}
|
||||
@ -1003,7 +1023,5 @@ HealthReportPolicy.prototype = {
|
||||
_futureDate: function _futureDate(offset) {
|
||||
return new Date(this.now().getTime() + offset);
|
||||
},
|
||||
};
|
||||
|
||||
Object.freeze(HealthReportPolicy.prototype);
|
||||
});
|
||||
|
16
services/datareporting/tests/Makefile.in
Normal file
16
services/datareporting/tests/Makefile.in
Normal file
@ -0,0 +1,16 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
XPCSHELL_TESTS = xpcshell
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -6,15 +6,19 @@
|
||||
const {utils: Cu} = Components;
|
||||
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
Cu.import("resource://gre/modules/services/healthreport/policy.jsm");
|
||||
Cu.import("resource://testing-common/services/healthreport/mocks.jsm");
|
||||
Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
|
||||
Cu.import("resource://testing-common/services/datareporting/mocks.jsm");
|
||||
|
||||
|
||||
function getPolicy(name) {
|
||||
let prefs = new Preferences(name);
|
||||
let listener = new MockPolicyListener();
|
||||
let branch = "testing.datareporting." + name;
|
||||
let policyPrefs = new Preferences(branch + ".policy.");
|
||||
let healthReportPrefs = new Preferences(branch + ".healthreport.");
|
||||
|
||||
return [new HealthReportPolicy(prefs, listener), prefs, listener];
|
||||
let listener = new MockPolicyListener();
|
||||
let policy = new DataReportingPolicy(policyPrefs, healthReportPrefs, listener);
|
||||
|
||||
return [policy, policyPrefs, healthReportPrefs, listener];
|
||||
}
|
||||
|
||||
function defineNow(policy, now) {
|
||||
@ -32,14 +36,15 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_test(function test_constructor() {
|
||||
let prefs = new Preferences("foo.bar");
|
||||
let policyPrefs = new Preferences("foo.bar.policy.");
|
||||
let hrPrefs = new Preferences("foo.bar.healthreport.");
|
||||
let listener = {
|
||||
onRequestDataUpload: function() {},
|
||||
onRequestRemoteDelete: function() {},
|
||||
onNotifyDataPolicy: function() {},
|
||||
};
|
||||
|
||||
let policy = new HealthReportPolicy(prefs, listener);
|
||||
let policy = new DataReportingPolicy(policyPrefs, hrPrefs, listener);
|
||||
do_check_true(Date.now() - policy.firstRunDate.getTime() < 1000);
|
||||
|
||||
let tomorrow = Date.now() + 24 * 60 * 60 * 1000;
|
||||
@ -51,68 +56,75 @@ add_test(function test_constructor() {
|
||||
});
|
||||
|
||||
add_test(function test_prefs() {
|
||||
let [policy, prefs, listener] = getPolicy("prefs");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("prefs");
|
||||
|
||||
let now = new Date();
|
||||
let nowT = now.getTime();
|
||||
|
||||
policy.firstRunDate = now;
|
||||
do_check_eq(prefs.get("firstRunTime"), nowT);
|
||||
do_check_eq(policyPrefs.get("firstRunTime"), nowT);
|
||||
do_check_eq(policy.firstRunDate.getTime(), nowT);
|
||||
|
||||
policy.dataSubmissionPolicyNotifiedDate= now;
|
||||
do_check_eq(prefs.get("dataSubmissionPolicyNotifiedTime"), nowT);
|
||||
do_check_eq(policyPrefs.get("dataSubmissionPolicyNotifiedTime"), nowT);
|
||||
do_check_eq(policy.dataSubmissionPolicyNotifiedDate.getTime(), nowT);
|
||||
|
||||
policy.dataSubmissionPolicyResponseDate = now;
|
||||
do_check_eq(prefs.get("dataSubmissionPolicyResponseTime"), nowT);
|
||||
do_check_eq(policyPrefs.get("dataSubmissionPolicyResponseTime"), nowT);
|
||||
do_check_eq(policy.dataSubmissionPolicyResponseDate.getTime(), nowT);
|
||||
|
||||
policy.dataSubmissionPolicyResponseType = "type-1";
|
||||
do_check_eq(prefs.get("dataSubmissionPolicyResponseType"), "type-1");
|
||||
do_check_eq(policyPrefs.get("dataSubmissionPolicyResponseType"), "type-1");
|
||||
do_check_eq(policy.dataSubmissionPolicyResponseType, "type-1");
|
||||
|
||||
policy.dataSubmissionEnabled = false;
|
||||
do_check_false(prefs.get("dataSubmissionEnabled", true));
|
||||
do_check_false(policyPrefs.get("dataSubmissionEnabled", true));
|
||||
do_check_false(policy.dataSubmissionEnabled);
|
||||
|
||||
policy.dataSubmissionPolicyAccepted = false;
|
||||
do_check_false(prefs.get("dataSubmissionPolicyAccepted", true));
|
||||
do_check_false(policyPrefs.get("dataSubmissionPolicyAccepted", true));
|
||||
do_check_false(policy.dataSubmissionPolicyAccepted);
|
||||
|
||||
policy.dataSubmissionPolicyAcceptedVersion = 2;
|
||||
do_check_eq(policyPrefs.get("dataSubmissionPolicyAcceptedVersion"), 2);
|
||||
|
||||
do_check_false(policy.dataSubmissionPolicyBypassAcceptance);
|
||||
prefs.set("dataSubmissionPolicyBypassAcceptance", true);
|
||||
policyPrefs.set("dataSubmissionPolicyBypassAcceptance", true);
|
||||
do_check_true(policy.dataSubmissionPolicyBypassAcceptance);
|
||||
|
||||
policy.lastDataSubmissionRequestedDate = now;
|
||||
do_check_eq(prefs.get("lastDataSubmissionRequestedTime"), nowT);
|
||||
do_check_eq(hrPrefs.get("lastDataSubmissionRequestedTime"), nowT);
|
||||
do_check_eq(policy.lastDataSubmissionRequestedDate.getTime(), nowT);
|
||||
|
||||
policy.lastDataSubmissionSuccessfulDate = now;
|
||||
do_check_eq(prefs.get("lastDataSubmissionSuccessfulTime"), nowT);
|
||||
do_check_eq(hrPrefs.get("lastDataSubmissionSuccessfulTime"), nowT);
|
||||
do_check_eq(policy.lastDataSubmissionSuccessfulDate.getTime(), nowT);
|
||||
|
||||
policy.lastDataSubmissionFailureDate = now;
|
||||
do_check_eq(prefs.get("lastDataSubmissionFailureTime"), nowT);
|
||||
do_check_eq(hrPrefs.get("lastDataSubmissionFailureTime"), nowT);
|
||||
do_check_eq(policy.lastDataSubmissionFailureDate.getTime(), nowT);
|
||||
|
||||
policy.nextDataSubmissionDate = now;
|
||||
do_check_eq(prefs.get("nextDataSubmissionTime"), nowT);
|
||||
do_check_eq(hrPrefs.get("nextDataSubmissionTime"), nowT);
|
||||
do_check_eq(policy.nextDataSubmissionDate.getTime(), nowT);
|
||||
|
||||
policy.currentDaySubmissionFailureCount = 2;
|
||||
do_check_eq(prefs.get("currentDaySubmissionFailureCount", 0), 2);
|
||||
do_check_eq(hrPrefs.get("currentDaySubmissionFailureCount", 0), 2);
|
||||
do_check_eq(policy.currentDaySubmissionFailureCount, 2);
|
||||
|
||||
policy.pendingDeleteRemoteData = true;
|
||||
do_check_true(prefs.get("pendingDeleteRemoteData"));
|
||||
do_check_true(hrPrefs.get("pendingDeleteRemoteData"));
|
||||
do_check_true(policy.pendingDeleteRemoteData);
|
||||
|
||||
policy.healthReportUploadEnabled = false;
|
||||
do_check_false(hrPrefs.get("uploadEnabled"));
|
||||
do_check_false(policy.healthReportUploadEnabled);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_notify_state_prefs() {
|
||||
let [policy, prefs, listener] = getPolicy("notify_state_prefs");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notify_state_prefs");
|
||||
|
||||
do_check_eq(policy.notifyState, policy.STATE_NOTIFY_UNNOTIFIED);
|
||||
|
||||
@ -127,7 +139,7 @@ add_test(function test_notify_state_prefs() {
|
||||
});
|
||||
|
||||
add_test(function test_initial_submission_notification() {
|
||||
let [policy, prefs, listener] = getPolicy("initial_submission_notification");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("initial_submission_notification");
|
||||
|
||||
do_check_eq(listener.notifyUserCount, 0);
|
||||
|
||||
@ -159,9 +171,9 @@ add_test(function test_initial_submission_notification() {
|
||||
});
|
||||
|
||||
add_test(function test_bypass_acceptance() {
|
||||
let [policy, prefs, listener] = getPolicy("bypass_acceptance");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("bypass_acceptance");
|
||||
|
||||
prefs.set("dataSubmissionPolicyBypassAcceptance", true);
|
||||
policyPrefs.set("dataSubmissionPolicyBypassAcceptance", true);
|
||||
do_check_false(policy.dataSubmissionPolicyAccepted);
|
||||
do_check_true(policy.dataSubmissionPolicyBypassAcceptance);
|
||||
defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime()));
|
||||
@ -172,7 +184,7 @@ add_test(function test_bypass_acceptance() {
|
||||
});
|
||||
|
||||
add_test(function test_notification_implicit_acceptance() {
|
||||
let [policy, prefs, listener] = getPolicy("notification_implicit_acceptance");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_implicit_acceptance");
|
||||
|
||||
let now = new Date(policy.nextDataSubmissionDate.getTime() -
|
||||
policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
|
||||
@ -202,7 +214,7 @@ add_test(function test_notification_implicit_acceptance() {
|
||||
|
||||
add_test(function test_notification_rejected() {
|
||||
// User notification failed. We should not record it as being presented.
|
||||
let [policy, prefs, listener] = getPolicy("notification_failed");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_failed");
|
||||
|
||||
let now = new Date(policy.nextDataSubmissionDate.getTime() -
|
||||
policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
|
||||
@ -218,7 +230,7 @@ add_test(function test_notification_rejected() {
|
||||
});
|
||||
|
||||
add_test(function test_notification_accepted() {
|
||||
let [policy, prefs, listener] = getPolicy("notification_accepted");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_accepted");
|
||||
|
||||
let now = new Date(policy.nextDataSubmissionDate.getTime() -
|
||||
policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
|
||||
@ -238,7 +250,7 @@ add_test(function test_notification_accepted() {
|
||||
});
|
||||
|
||||
add_test(function test_notification_rejected() {
|
||||
let [policy, prefs, listener] = getPolicy("notification_rejected");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("notification_rejected");
|
||||
|
||||
let now = new Date(policy.nextDataSubmissionDate.getTime() -
|
||||
policy.SUBMISSION_NOTIFY_INTERVAL_MSEC + 1);
|
||||
@ -261,11 +273,12 @@ add_test(function test_notification_rejected() {
|
||||
});
|
||||
|
||||
add_test(function test_submission_kill_switch() {
|
||||
let [policy, prefs, listener] = getPolicy("submission_kill_switch");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_kill_switch");
|
||||
|
||||
policy.firstRunDate = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000);
|
||||
policy.nextDataSubmissionDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
policy.recordUserAcceptance("accept-old-ack");
|
||||
do_check_eq(policyPrefs.get("dataSubmissionPolicyAcceptedVersion"), 1);
|
||||
policy.checkStateAndTrigger();
|
||||
do_check_eq(listener.requestDataUploadCount, 1);
|
||||
|
||||
@ -279,16 +292,16 @@ add_test(function test_submission_kill_switch() {
|
||||
});
|
||||
|
||||
add_test(function test_upload_kill_switch() {
|
||||
let [policy, prefs, listener] = getPolicy("upload_kill_switch");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("upload_kill_switch");
|
||||
|
||||
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
|
||||
policy.recordUserAcceptance();
|
||||
defineNow(policy, policy.nextDataSubmissionDate);
|
||||
|
||||
policy.dataUploadEnabled = false;
|
||||
policy.healthReportUploadEnabled = false;
|
||||
policy.checkStateAndTrigger();
|
||||
do_check_eq(listener.requestDataUploadCount, 0);
|
||||
policy.dataUploadEnabled = true;
|
||||
policy.healthReportUploadEnabled = true;
|
||||
policy.checkStateAndTrigger();
|
||||
do_check_eq(listener.requestDataUploadCount, 1);
|
||||
|
||||
@ -296,7 +309,7 @@ add_test(function test_upload_kill_switch() {
|
||||
});
|
||||
|
||||
add_test(function test_data_submission_no_data() {
|
||||
let [policy, prefs, listener] = getPolicy("data_submission_no_data");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_no_data");
|
||||
|
||||
policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
policy.dataSubmissionPolicyAccepted = true;
|
||||
@ -316,7 +329,7 @@ add_test(function test_data_submission_no_data() {
|
||||
});
|
||||
|
||||
add_test(function test_data_submission_submit_failure_hard() {
|
||||
let [policy, prefs, listener] = getPolicy("data_submission_submit_failure_hard");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_submit_failure_hard");
|
||||
|
||||
policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
policy.dataSubmissionPolicyAccepted = true;
|
||||
@ -341,7 +354,7 @@ add_test(function test_data_submission_submit_failure_hard() {
|
||||
});
|
||||
|
||||
add_test(function test_data_submission_submit_try_again() {
|
||||
let [policy, prefs, listener] = getPolicy("data_submission_failure_soft");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("data_submission_failure_soft");
|
||||
|
||||
policy.recordUserAcceptance();
|
||||
let nextDataSubmissionDate = policy.nextDataSubmissionDate;
|
||||
@ -356,7 +369,7 @@ add_test(function test_data_submission_submit_try_again() {
|
||||
});
|
||||
|
||||
add_test(function test_submission_daily_scheduling() {
|
||||
let [policy, prefs, listener] = getPolicy("submission_daily_scheduling");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_daily_scheduling");
|
||||
|
||||
policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
policy.dataSubmissionPolicyAccepted = true;
|
||||
@ -396,7 +409,7 @@ add_test(function test_submission_daily_scheduling() {
|
||||
});
|
||||
|
||||
add_test(function test_submission_far_future_scheduling() {
|
||||
let [policy, prefs, listener] = getPolicy("submission_far_future_scheduling");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_far_future_scheduling");
|
||||
|
||||
let now = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
defineNow(policy, now);
|
||||
@ -420,7 +433,7 @@ add_test(function test_submission_far_future_scheduling() {
|
||||
});
|
||||
|
||||
add_test(function test_submission_backoff() {
|
||||
let [policy, prefs, listener] = getPolicy("submission_backoff");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_backoff");
|
||||
|
||||
do_check_eq(policy.FAILURE_BACKOFF_INTERVALS.length, 2);
|
||||
|
||||
@ -483,7 +496,7 @@ add_test(function test_submission_backoff() {
|
||||
|
||||
// Ensure that only one submission request can be active at a time.
|
||||
add_test(function test_submission_expiring() {
|
||||
let [policy, prefs, listener] = getPolicy("submission_expiring");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("submission_expiring");
|
||||
|
||||
policy.dataSubmissionPolicyResponseDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
policy.dataSubmissionPolicyAccepted = true;
|
||||
@ -506,7 +519,7 @@ add_test(function test_submission_expiring() {
|
||||
});
|
||||
|
||||
add_test(function test_delete_remote_data() {
|
||||
let [policy, prefs, listener] = getPolicy("delete_remote_data");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data");
|
||||
|
||||
do_check_false(policy.pendingDeleteRemoteData);
|
||||
let nextSubmissionDate = policy.nextDataSubmissionDate;
|
||||
@ -532,7 +545,7 @@ add_test(function test_delete_remote_data() {
|
||||
|
||||
// Ensure that deletion requests take priority over regular data submission.
|
||||
add_test(function test_delete_remote_data_priority() {
|
||||
let [policy, prefs, listener] = getPolicy("delete_remote_data_priority");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_priority");
|
||||
|
||||
let now = new Date();
|
||||
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
|
||||
@ -553,7 +566,7 @@ add_test(function test_delete_remote_data_priority() {
|
||||
});
|
||||
|
||||
add_test(function test_delete_remote_data_backoff() {
|
||||
let [policy, prefs, listener] = getPolicy("delete_remote_data_backoff");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_backoff");
|
||||
|
||||
let now = new Date();
|
||||
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
|
||||
@ -586,7 +599,7 @@ add_test(function test_delete_remote_data_backoff() {
|
||||
// If we request delete while an upload is in progress, delete should be
|
||||
// scheduled immediately after upload.
|
||||
add_test(function test_delete_remote_data_in_progress_upload() {
|
||||
let [policy, prefs, listener] = getPolicy("delete_remote_data_in_progress_upload");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("delete_remote_data_in_progress_upload");
|
||||
|
||||
let now = new Date();
|
||||
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
|
||||
@ -616,7 +629,7 @@ add_test(function test_delete_remote_data_in_progress_upload() {
|
||||
});
|
||||
|
||||
add_test(function test_polling() {
|
||||
let [policy, prefs, listener] = getPolicy("polling");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("polling");
|
||||
|
||||
// Ensure checkStateAndTrigger is called at a regular interval.
|
||||
let now = new Date();
|
||||
@ -632,7 +645,7 @@ add_test(function test_polling() {
|
||||
|
||||
do_check_true(now2.getTime() - now.getTime() >= 500);
|
||||
now = now2;
|
||||
HealthReportPolicy.prototype.checkStateAndTrigger.call(policy);
|
||||
DataReportingPolicy.prototype.checkStateAndTrigger.call(policy);
|
||||
|
||||
if (count >= 2) {
|
||||
policy.stopPolling();
|
||||
@ -652,7 +665,7 @@ add_test(function test_polling() {
|
||||
// This is probably covered by other tests. But, it's best to have explicit
|
||||
// coverage from a higher-level.
|
||||
add_test(function test_polling_implicit_acceptance() {
|
||||
let [policy, prefs, listener] = getPolicy("polling_implicit_acceptance");
|
||||
let [policy, policyPrefs, hrPrefs, listener] = getPolicy("polling_implicit_acceptance");
|
||||
|
||||
// Redefine intervals with shorter, test-friendly values.
|
||||
Object.defineProperty(policy, "POLL_INTERVAL_MSEC", {
|
||||
@ -670,7 +683,7 @@ add_test(function test_polling_implicit_acceptance() {
|
||||
print("checkStateAndTrigger count: " + count);
|
||||
|
||||
// Account for some slack.
|
||||
HealthReportPolicy.prototype.checkStateAndTrigger.call(policy);
|
||||
DataReportingPolicy.prototype.checkStateAndTrigger.call(policy);
|
||||
|
||||
// What should happen on different invocations:
|
||||
//
|
5
services/datareporting/tests/xpcshell/xpcshell.ini
Normal file
5
services/datareporting/tests/xpcshell/xpcshell.ini
Normal file
@ -0,0 +1,5 @@
|
||||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_policy.js]
|
@ -1,14 +1,4 @@
|
||||
# b2g: {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
|
||||
# browser: {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
|
||||
# mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
|
||||
# mobile/xul: {a23983c0-fd0e-11dc-95ff-0800200c9a66}
|
||||
# suite (comm): {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
|
||||
# metro browser: {99bceaaa-e3c6-48c1-b981-ef9b46b67d60}
|
||||
|
||||
component {e354c59b-b252-4040-b6dd-b71864e3e35c} HealthReportService.js
|
||||
contract @mozilla.org/healthreport/service;1 {e354c59b-b252-4040-b6dd-b71864e3e35c}
|
||||
category app-startup HealthReportService service,@mozilla.org/healthreport/service;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}
|
||||
|
||||
# Register Firefox Health Report providers.
|
||||
category healthreport-js-provider AddonsProvider resource://gre/modules/services/healthreport/providers.jsm
|
||||
category healthreport-js-provider AppInfoProvider resource://gre/modules/services/healthreport/providers.jsm
|
||||
category healthreport-js-provider CrashesProvider resource://gre/modules/services/healthreport/providers.jsm
|
||||
|
@ -11,13 +11,11 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
modules := \
|
||||
healthreporter.jsm \
|
||||
policy.jsm \
|
||||
profile.jsm \
|
||||
providers.jsm \
|
||||
$(NULL)
|
||||
|
||||
testing_modules := \
|
||||
mocks.jsm \
|
||||
utils.jsm \
|
||||
$(NULL)
|
||||
|
||||
@ -32,7 +30,6 @@ TESTING_JS_MODULE_DIR := services/healthreport
|
||||
|
||||
EXTRA_COMPONENTS := \
|
||||
HealthReportComponents.manifest \
|
||||
HealthReportService.js \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -2,23 +2,24 @@
|
||||
* 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/. */
|
||||
|
||||
pref("healthreport.documentServerURI", "https://data.mozilla.com/");
|
||||
pref("healthreport.documentServerNamespace", "metrics");
|
||||
pref("healthreport.logging.consoleEnabled", true);
|
||||
pref("healthreport.logging.consoleLevel", "Warn");
|
||||
pref("healthreport.policy.currentDaySubmissionFailureCount", 0);
|
||||
pref("healthreport.policy.dataSubmissionEnabled", true);
|
||||
pref("healthreport.policy.dataSubmissionPolicyAccepted", false);
|
||||
pref("healthreport.policy.dataSubmissionPolicyBypassAcceptance", false);
|
||||
pref("healthreport.policy.dataSubmissionPolicyNotifiedTime", "0");
|
||||
pref("healthreport.policy.dataSubmissionPolicyResponseType", "");
|
||||
pref("healthreport.policy.dataSubmissionPolicyResponseTime", "0");
|
||||
pref("healthreport.policy.firstRunTime", "0");
|
||||
pref("healthreport.policy.lastDataSubmissionFailureTime", "0");
|
||||
pref("healthreport.policy.lastDataSubmissionRequestedTime", "0");
|
||||
pref("healthreport.policy.lastDataSubmissionSuccessfulTime", "0");
|
||||
pref("healthreport.policy.nextDataSubmissionTime", "0");
|
||||
pref("healthreport.service.enabled", true);
|
||||
pref("healthreport.service.loadDelayMsec", 10000);
|
||||
pref("healthreport.service.providerCategories", "healthreport-js-provider");
|
||||
pref("datareporting.healthreport.currentDaySubmissionFailureCount", 0);
|
||||
pref("datareporting.healthreport.documentServerURI", "https://data.mozilla.com/");
|
||||
pref("datareporting.healthreport.documentServerNamespace", "metrics");
|
||||
pref("datareporting.healthreport.infoURL", "http://www.mozilla.org/legal/privacy/firefox.html#health-report");
|
||||
pref("datareporting.healthreport.logging.consoleEnabled", true);
|
||||
pref("datareporting.healthreport.logging.consoleLevel", "Warn");
|
||||
pref("datareporting.healthreport.lastDataSubmissionFailureTime", "0");
|
||||
pref("datareporting.healthreport.lastDataSubmissionRequestedTime", "0");
|
||||
pref("datareporting.healthreport.lastDataSubmissionSuccessfulTime", "0");
|
||||
pref("datareporting.healthreport.nextDataSubmissionTime", "0");
|
||||
pref("datareporting.healthreport.pendingDeleteRemoteData", false);
|
||||
|
||||
// Health Report is enabled by default on all channels.
|
||||
pref("datareporting.healthreport.uploadEnabled", true);
|
||||
|
||||
pref("datareporting.healthreport.service.enabled", true);
|
||||
pref("datareporting.healthreport.service.loadDelayMsec", 10000);
|
||||
pref("datareporting.healthreport.service.providerCategories", "healthreport-js-provider");
|
||||
|
||||
pref("datareporting.healthreport.about.glossaryUrl", "https://services.mozilla.com/healthreport/glossary.html");
|
||||
pref("datareporting.healthreport.about.reportUrl", "https://services.mozilla.com/healthreport/placeholder.html");
|
||||
|
@ -11,7 +11,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://services-common/async.js");
|
||||
Cu.import("resource://services-common/bagheeraclient.js");
|
||||
Cu.import("resource://services-common/log4moz.js");
|
||||
Cu.import("resource://services-common/observers.js");
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
Cu.import("resource://services-common/utils.js");
|
||||
Cu.import("resource://gre/modules/commonjs/promise/core.js");
|
||||
@ -20,7 +19,6 @@ Cu.import("resource://gre/modules/osfile.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/services/healthreport/policy.jsm");
|
||||
|
||||
|
||||
// Oldest year to allow in date preferences. This module was implemented in
|
||||
@ -81,12 +79,19 @@ const DEFAULT_DATABASE_NAME = "healthreport.sqlite";
|
||||
* @param branch
|
||||
* (string) The preferences branch to use for state storage. The value
|
||||
* must end with a period (.).
|
||||
*
|
||||
* @param policy
|
||||
* (HealthReportPolicy) Policy driving execution of HealthReporter.
|
||||
*/
|
||||
function HealthReporter(branch) {
|
||||
function HealthReporter(branch, policy) {
|
||||
if (!branch.endsWith(".")) {
|
||||
throw new Error("Branch must end with a period (.): " + branch);
|
||||
}
|
||||
|
||||
if (!policy) {
|
||||
throw new Error("Must provide policy to HealthReporter constructor.");
|
||||
}
|
||||
|
||||
this._log = Log4Moz.repository.getLogger("Services.HealthReport.HealthReporter");
|
||||
this._log.info("Initializing health reporter instance against " + branch);
|
||||
|
||||
@ -100,10 +105,9 @@ function HealthReporter(branch) {
|
||||
throw new Error("No server namespace defined. Did you forget a pref?");
|
||||
}
|
||||
|
||||
this._dbName = this._prefs.get("dbName") || DEFAULT_DATABASE_NAME;
|
||||
this._policy = policy;
|
||||
|
||||
let policyBranch = new Preferences(branch + "policy.");
|
||||
this._policy = new HealthReportPolicy(policyBranch, this);
|
||||
this._dbName = this._prefs.get("dbName") || DEFAULT_DATABASE_NAME;
|
||||
|
||||
this._storage = null;
|
||||
this._storageInProgress = false;
|
||||
@ -210,6 +214,14 @@ HealthReporter.prototype = Object.freeze({
|
||||
this._prefs.set("lastSubmitID", value || "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether this instance will upload data to a server.
|
||||
*/
|
||||
get willUploadData() {
|
||||
return this._policy.dataSubmissionPolicyAccepted &&
|
||||
this._policy.healthReportUploadEnabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether remote data is currently stored.
|
||||
*
|
||||
@ -289,7 +301,6 @@ HealthReporter.prototype = Object.freeze({
|
||||
return;
|
||||
}
|
||||
|
||||
this._policy.startPolling();
|
||||
this._log.info("HealthReporter started.");
|
||||
this._initialized = true;
|
||||
Services.obs.addObserver(this, "idle-daily", false);
|
||||
@ -327,9 +338,6 @@ HealthReporter.prototype = Object.freeze({
|
||||
this._initialized = false;
|
||||
this._shutdownRequested = true;
|
||||
|
||||
// Safe to call multiple times.
|
||||
this._policy.stopPolling();
|
||||
|
||||
if (this._collectorInProgress) {
|
||||
this._log.warn("Collector is in progress of initializing. Waiting to finish.");
|
||||
return;
|
||||
@ -552,45 +560,14 @@ HealthReporter.prototype = Object.freeze({
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the user's rejection of the data submission policy.
|
||||
* Called to initiate a data upload.
|
||||
*
|
||||
* This should be what everything uses to disable data submission.
|
||||
*
|
||||
* @param reason
|
||||
* (string) Why data submission is being disabled.
|
||||
* The passed argument is a `DataSubmissionRequest` from policy.jsm.
|
||||
*/
|
||||
recordPolicyRejection: function (reason) {
|
||||
this._policy.recordUserRejection(reason);
|
||||
},
|
||||
|
||||
/**
|
||||
* Record the user's acceptance of the data submission policy.
|
||||
*
|
||||
* This should be what everything uses to enable data submission.
|
||||
*
|
||||
* @param reason
|
||||
* (string) Why data submission is being enabled.
|
||||
*/
|
||||
recordPolicyAcceptance: function (reason) {
|
||||
this._policy.recordUserAcceptance(reason);
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the data submission policy has been accepted.
|
||||
*
|
||||
* If this is true, health data will be submitted unless one of the kill
|
||||
* switches is active.
|
||||
*/
|
||||
get dataSubmissionPolicyAccepted() {
|
||||
return this._policy.dataSubmissionPolicyAccepted;
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether this health reporter will upload data to a server.
|
||||
*/
|
||||
get willUploadData() {
|
||||
return this._policy.dataSubmissionPolicyAccepted &&
|
||||
this._policy.dataUploadEnabled;
|
||||
requestDataUpload: function (request) {
|
||||
this.collectMeasurements()
|
||||
.then(this._uploadData.bind(this, request),
|
||||
this._onSubmitDataRequestFailure.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -768,7 +745,7 @@ HealthReporter.prototype = Object.freeze({
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_deleteRemoteData: function (request) {
|
||||
deleteRemoteData: function (request) {
|
||||
if (!this.lastSubmitID) {
|
||||
this._log.info("Received request to delete remote data but no data stored.");
|
||||
request.onNoDataAvailable();
|
||||
@ -859,28 +836,5 @@ HealthReporter.prototype = Object.freeze({
|
||||
return new Date();
|
||||
},
|
||||
|
||||
//-----------------------------
|
||||
// HealthReportPolicy listeners
|
||||
//-----------------------------
|
||||
|
||||
onRequestDataUpload: function (request) {
|
||||
this.collectMeasurements()
|
||||
.then(this._uploadData.bind(this, request),
|
||||
this._onSubmitDataRequestFailure.bind(this));
|
||||
},
|
||||
|
||||
onNotifyDataPolicy: function (request) {
|
||||
// This isn't very loosely coupled. We may want to have this call
|
||||
// registered listeners instead.
|
||||
Observers.notify("healthreport:notify-data-policy:request", request);
|
||||
},
|
||||
|
||||
onRequestRemoteDelete: function (request) {
|
||||
this._deleteRemoteData(request);
|
||||
},
|
||||
|
||||
//------------------------------------
|
||||
// End of HealthReportPolicy listeners
|
||||
//------------------------------------
|
||||
});
|
||||
|
||||
|
@ -216,8 +216,8 @@ this.createFakeCrash = function (submitted=false, date=new Date()) {
|
||||
*
|
||||
* The purpose of this type is to aid testing of startup and shutdown.
|
||||
*/
|
||||
this.InspectedHealthReporter = function (branch) {
|
||||
HealthReporter.call(this, branch);
|
||||
this.InspectedHealthReporter = function (branch, policy) {
|
||||
HealthReporter.call(this, branch, policy);
|
||||
|
||||
this.onStorageCreated = null;
|
||||
this.onCollectorInitialized = null;
|
||||
|
@ -728,6 +728,13 @@ AddonsProvider.prototype = Object.freeze({
|
||||
"onUninstalled",
|
||||
],
|
||||
|
||||
// Add-on types for which full details are uploaded in the
|
||||
// ActiveAddonsMeasurement. All other types are ignored.
|
||||
FULL_DETAIL_TYPES: [
|
||||
"plugin",
|
||||
"extension",
|
||||
],
|
||||
|
||||
name: "org.mozilla.addons",
|
||||
|
||||
measurementTypes: [
|
||||
@ -815,6 +822,13 @@ AddonsProvider.prototype = Object.freeze({
|
||||
let data = {addons: {}, counts: {}};
|
||||
|
||||
for (let addon of addons) {
|
||||
let type = addon.type;
|
||||
data.counts[type] = (data.counts[type] || 0) + 1;
|
||||
|
||||
if (this.FULL_DETAIL_TYPES.indexOf(addon.type) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let optOutPref = "extensions." + addon.id + ".getAddons.cache.enabled";
|
||||
if (!this._prefs.get(optOutPref, true)) {
|
||||
this._log.debug("Ignoring add-on that's opted out of AMO updates: " +
|
||||
@ -837,8 +851,6 @@ AddonsProvider.prototype = Object.freeze({
|
||||
|
||||
data.addons[addon.id] = obj;
|
||||
|
||||
let type = addon.type;
|
||||
data.counts[type] = (data.counts[type] || 0) + 1;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -9,7 +9,7 @@ Cu.import("resource://services-common/observers.js");
|
||||
Cu.import("resource://services-common/preferences.js");
|
||||
Cu.import("resource://gre/modules/commonjs/promise/core.js");
|
||||
Cu.import("resource://gre/modules/services/healthreport/healthreporter.jsm");
|
||||
Cu.import("resource://gre/modules/services/healthreport/policy.jsm");
|
||||
Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://testing-common/services-common/bagheeraserver.js");
|
||||
@ -36,12 +36,29 @@ function defineNow(policy, now) {
|
||||
function getJustReporter(name, uri=SERVER_URI, inspected=false) {
|
||||
let branch = "healthreport.testing. " + name + ".";
|
||||
|
||||
let prefs = new Preferences(branch);
|
||||
let prefs = new Preferences(branch + "healthreport.");
|
||||
prefs.set("documentServerURI", uri);
|
||||
prefs.set("dbName", name);
|
||||
|
||||
let reporter;
|
||||
|
||||
let policyPrefs = new Preferences(branch + "policy.");
|
||||
let policy = new DataReportingPolicy(policyPrefs, prefs, {
|
||||
onRequestDataUpload: function (request) {
|
||||
reporter.requestDataUpload(request);
|
||||
},
|
||||
|
||||
onNotifyDataPolicy: function (request) { },
|
||||
|
||||
onRequestRemoteDelete: function (request) {
|
||||
reporter.deleteRemoteData(request);
|
||||
},
|
||||
});
|
||||
|
||||
let type = inspected ? InspectedHealthReporter : HealthReporter;
|
||||
return new type(branch);
|
||||
reporter = new type(branch + "healthreport.", policy);
|
||||
|
||||
return reporter;
|
||||
}
|
||||
|
||||
function getReporter(name, uri, inspected) {
|
||||
@ -251,7 +268,7 @@ add_task(function test_data_submission_transport_failure() {
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let request = new DataSubmissionRequest(deferred, new Date(Date.now + 30000));
|
||||
reporter.onRequestDataUpload(request);
|
||||
reporter.requestDataUpload(request);
|
||||
|
||||
yield deferred.promise;
|
||||
do_check_eq(request.state, request.SUBMISSION_FAILURE_SOFT);
|
||||
@ -268,7 +285,7 @@ add_task(function test_data_submission_success() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let request = new DataSubmissionRequest(deferred, new Date());
|
||||
reporter.onRequestDataUpload(request);
|
||||
reporter.requestDataUpload(request);
|
||||
yield deferred.promise;
|
||||
do_check_eq(request.state, request.SUBMISSION_SUCCESS);
|
||||
do_check_true(reporter.lastPingDate.getTime() > 0);
|
||||
@ -336,22 +353,23 @@ add_task(function test_request_remote_data_deletion() {
|
||||
add_task(function test_policy_accept_reject() {
|
||||
let [reporter, server] = yield getReporterAndServer("policy_accept_reject");
|
||||
|
||||
do_check_false(reporter.dataSubmissionPolicyAccepted);
|
||||
let policy = reporter._policy;
|
||||
|
||||
do_check_false(policy.dataSubmissionPolicyAccepted);
|
||||
do_check_false(reporter.willUploadData);
|
||||
|
||||
reporter.recordPolicyAcceptance();
|
||||
do_check_true(reporter.dataSubmissionPolicyAccepted);
|
||||
policy.recordUserAcceptance();
|
||||
do_check_true(policy.dataSubmissionPolicyAccepted);
|
||||
do_check_true(reporter.willUploadData);
|
||||
|
||||
reporter.recordPolicyRejection();
|
||||
do_check_false(reporter.dataSubmissionPolicyAccepted);
|
||||
policy.recordUserRejection();
|
||||
do_check_false(policy.dataSubmissionPolicyAccepted);
|
||||
do_check_false(reporter.willUploadData);
|
||||
|
||||
reporter._shutdown();
|
||||
yield shutdownServer(server);
|
||||
});
|
||||
|
||||
|
||||
add_task(function test_upload_save_payload() {
|
||||
let [reporter, server] = yield getReporterAndServer("upload_save_payload");
|
||||
|
||||
|
@ -5,24 +5,14 @@
|
||||
|
||||
const modules = [
|
||||
"healthreporter.jsm",
|
||||
"policy.jsm",
|
||||
"profile.jsm",
|
||||
"providers.jsm",
|
||||
];
|
||||
|
||||
const test_modules = [
|
||||
"mocks.jsm",
|
||||
];
|
||||
|
||||
function run_test() {
|
||||
for (let m of modules) {
|
||||
let resource = "resource://gre/modules/services/healthreport/" + m;
|
||||
Components.utils.import(resource, {});
|
||||
}
|
||||
|
||||
for (let m of test_modules) {
|
||||
let resource = "resource://testing-common/services/healthreport/" + m;
|
||||
Components.utils.import(resource, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,19 @@ add_task(function test_collect() {
|
||||
installDate: now,
|
||||
updateDate: now,
|
||||
},
|
||||
// Is counted but full details are omitted because it is a theme.
|
||||
{
|
||||
id: "addon2",
|
||||
userDisabled: false,
|
||||
appDisabled: false,
|
||||
version: "3",
|
||||
type: "theme",
|
||||
scope: 1,
|
||||
foreignInstall: false,
|
||||
hasBinaryComponents: false,
|
||||
installDate: now,
|
||||
updateDate: now,
|
||||
},
|
||||
];
|
||||
|
||||
monkeypatchAddons(provider, addons);
|
||||
@ -109,9 +122,10 @@ add_task(function test_collect() {
|
||||
do_check_true(data.days.hasDay(now));
|
||||
|
||||
value = data.days.getDay(now);
|
||||
do_check_eq(value.size, 2);
|
||||
do_check_eq(value.size, 3);
|
||||
do_check_eq(value.get("extension"), 1);
|
||||
do_check_eq(value.get("plugin"), 1);
|
||||
do_check_eq(value.get("theme"), 1);
|
||||
|
||||
yield provider.shutdown();
|
||||
yield storage.close();
|
||||
|
@ -4,7 +4,6 @@ tail =
|
||||
|
||||
[test_load_modules.js]
|
||||
[test_profile.js]
|
||||
[test_policy.js]
|
||||
[test_healthreporter.js]
|
||||
[test_provider_addons.js]
|
||||
[test_provider_appinfo.js]
|
||||
|
@ -9,6 +9,7 @@ add_makefiles "
|
||||
services/crypto/Makefile
|
||||
services/crypto/component/Makefile
|
||||
services/healthreport/Makefile
|
||||
services/datareporting/Makefile
|
||||
services/metrics/Makefile
|
||||
services/sync/Makefile
|
||||
services/sync/locales/Makefile
|
||||
@ -20,6 +21,7 @@ if [ "$ENABLE_TESTS" ]; then
|
||||
services/common/tests/Makefile
|
||||
services/crypto/tests/Makefile
|
||||
services/healthreport/tests/Makefile
|
||||
services/datareporting/tests/Makefile
|
||||
services/metrics/tests/Makefile
|
||||
services/sync/tests/Makefile
|
||||
"
|
||||
|
@ -83,7 +83,7 @@ Collector.prototype = Object.freeze({
|
||||
return;
|
||||
}
|
||||
|
||||
let [provider, deferred] = this._providerInitQueue.pop();
|
||||
let [provider, deferred] = this._providerInitQueue.shift();
|
||||
this._providerInitializing = true;
|
||||
|
||||
this._log.info("Initializing provider with storage: " + provider.name);
|
||||
|
@ -1251,6 +1251,7 @@ MetricsStorageSqliteBackend.prototype = Object.freeze({
|
||||
throw new Error("enqueueOperation expects a function. Got: " + typeof(func));
|
||||
}
|
||||
|
||||
this._log.trace("Enqueueing operation.");
|
||||
let deferred = Promise.defer();
|
||||
|
||||
this._queuedOperations.push([func, deferred]);
|
||||
@ -1268,7 +1269,7 @@ MetricsStorageSqliteBackend.prototype = Object.freeze({
|
||||
}
|
||||
|
||||
this._log.trace("Performing queued operation.");
|
||||
let [func, deferred] = this._queuedOperations.pop();
|
||||
let [func, deferred] = this._queuedOperations.shift();
|
||||
let promise;
|
||||
|
||||
try {
|
||||
|
@ -195,6 +195,50 @@ add_task(function test_field_registration_repopulation() {
|
||||
yield backend.close();
|
||||
});
|
||||
|
||||
add_task(function test_enqueue_operation_execution_order() {
|
||||
let backend = yield Metrics.Storage("enqueue_operation_execution_order");
|
||||
|
||||
let executionCount = 0;
|
||||
|
||||
let fns = {
|
||||
op1: function () {
|
||||
do_check_eq(executionCount, 1);
|
||||
},
|
||||
|
||||
op2: function () {
|
||||
do_check_eq(executionCount, 2);
|
||||
},
|
||||
|
||||
op3: function () {
|
||||
do_check_eq(executionCount, 3);
|
||||
},
|
||||
};
|
||||
|
||||
function enqueuedOperation(fn) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
CommonUtils.nextTick(function onNextTick() {
|
||||
executionCount++;
|
||||
fn();
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
let promises = [];
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
let fn = fns["op" + i];
|
||||
promises.push(backend.enqueueOperation(enqueuedOperation.bind(this, fn)));
|
||||
}
|
||||
|
||||
for (let promise of promises) {
|
||||
yield promise;
|
||||
}
|
||||
|
||||
yield backend.close();
|
||||
});
|
||||
|
||||
add_task(function test_enqueue_operation_many() {
|
||||
let backend = yield Metrics.Storage("enqueue_operation_many");
|
||||
|
||||
|
@ -6,4 +6,3 @@ tail =
|
||||
[test_metrics_provider.js]
|
||||
[test_metrics_collector.js]
|
||||
[test_metrics_storage.js]
|
||||
skip-if = true
|
||||
|
@ -89,6 +89,7 @@ Tracker.prototype = {
|
||||
return;
|
||||
}
|
||||
Utils.namedTimer(function() {
|
||||
this._log.debug("Saving changed IDs to " + this.file);
|
||||
Utils.jsonSave("changes/" + this.file, this, this.changedIDs, cb);
|
||||
}, 1000, this, "_lazySave");
|
||||
},
|
||||
@ -136,7 +137,7 @@ Tracker.prototype = {
|
||||
|
||||
// Add/update the entry if we have a newer time
|
||||
if ((this.changedIDs[id] || -Infinity) < when) {
|
||||
this._log.trace("Adding changed ID: " + [id, when]);
|
||||
this._log.trace("Adding changed ID: " + id + ", " + when);
|
||||
this.changedIDs[id] = when;
|
||||
this.saveChangedIDs(this.onSavedChangedIDs);
|
||||
}
|
||||
|
@ -405,8 +405,10 @@ HistoryTracker.prototype = {
|
||||
|
||||
onVisit: function (uri, vid, time, session, referrer, trans, guid) {
|
||||
if (this.ignoreAll) {
|
||||
this._log.trace("ignoreAll: ignoring visit for " + guid);
|
||||
return;
|
||||
}
|
||||
|
||||
this._log.trace("onVisit: " + uri.spec);
|
||||
if (this.addChangedID(guid)) {
|
||||
this.score += SCORE_INCREMENT_SMALL;
|
||||
|
@ -30,7 +30,9 @@ tracker.persistChangedIDs = false;
|
||||
|
||||
let _counter = 0;
|
||||
function addVisit() {
|
||||
let uri = Utils.makeURI("http://getfirefox.com/" + _counter);
|
||||
let uriString = "http://getfirefox.com/" + _counter++;
|
||||
let uri = Utils.makeURI(uriString);
|
||||
_("Adding visit for URI " + uriString);
|
||||
let place = {
|
||||
uri: uri,
|
||||
visits: [ {
|
||||
@ -38,26 +40,30 @@ function addVisit() {
|
||||
transitionType: PlacesUtils.history.TRANSITION_LINK
|
||||
} ]
|
||||
};
|
||||
|
||||
let cb = Async.makeSpinningCallback();
|
||||
PlacesUtils.asyncHistory.updatePlaces(place, {
|
||||
handleError: function Add_handleError() {
|
||||
_("Error adding visit for " + uriString);
|
||||
cb(new Error("Error adding history entry"));
|
||||
},
|
||||
handleResult: function Add_handleResult() {
|
||||
_("Added visit for " + uriString);
|
||||
cb();
|
||||
},
|
||||
handleCompletion: function Add_handleCompletion() {
|
||||
// Nothing to do
|
||||
}
|
||||
});
|
||||
// Spin the event loop to embed this async call in a sync API
|
||||
|
||||
// Spin the event loop to embed this async call in a sync API.
|
||||
cb.wait();
|
||||
_counter++;
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
function run_test() {
|
||||
initTestLogging("Trace");
|
||||
Log4Moz.repository.getLogger("Sync.Tracker.History").level = Log4Moz.Level.Trace;
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
@ -91,6 +97,7 @@ add_test(function test_start_tracking() {
|
||||
|
||||
_("Tell the tracker to start tracking changes.");
|
||||
onScoreUpdated(function() {
|
||||
_("Score updated in test_start_tracking.");
|
||||
do_check_attribute_count(tracker.changedIDs, 1);
|
||||
do_check_eq(tracker.score, SCORE_INCREMENT_SMALL);
|
||||
run_next_test();
|
||||
@ -101,12 +108,18 @@ add_test(function test_start_tracking() {
|
||||
});
|
||||
|
||||
add_test(function test_start_tracking_twice() {
|
||||
_("Verifying preconditions from test_start_tracking.");
|
||||
do_check_attribute_count(tracker.changedIDs, 1);
|
||||
do_check_eq(tracker.score, SCORE_INCREMENT_SMALL);
|
||||
|
||||
_("Notifying twice won't do any harm.");
|
||||
onScoreUpdated(function() {
|
||||
_("Score updated in test_start_tracking_twice.");
|
||||
do_check_attribute_count(tracker.changedIDs, 2);
|
||||
do_check_eq(tracker.score, 2 * SCORE_INCREMENT_SMALL);
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
Svc.Obs.notify("weave:engine:start-tracking");
|
||||
addVisit();
|
||||
});
|
||||
|
@ -3,99 +3,97 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from threading import RLock
|
||||
|
||||
from tps import TPSFirefoxRunner, TPSTestRunner
|
||||
from tps import TPSTestRunner
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("--mobile",
|
||||
action = "store_true", dest = "mobile",
|
||||
default = False,
|
||||
help = "run with mobile settings")
|
||||
parser.add_option("--testfile",
|
||||
action = "store", type = "string", dest = "testfile",
|
||||
default = '../../services/sync/tests/tps/test_sync.js',
|
||||
help = "path to the test file to run "
|
||||
"[default: %default]")
|
||||
parser.add_option("--logfile",
|
||||
action = "store", type = "string", dest = "logfile",
|
||||
default = 'tps.log',
|
||||
help = "path to the log file [default: %default]")
|
||||
parser.add_option("--resultfile",
|
||||
action = "store", type = "string", dest = "resultfile",
|
||||
default = 'tps_result.json',
|
||||
help = "path to the result file [default: %default]")
|
||||
parser.add_option("--binary",
|
||||
action = "store", type = "string", dest = "binary",
|
||||
default = None,
|
||||
help = "path to the Firefox binary, specified either as "
|
||||
"a local file or a url; if omitted, the PATH "
|
||||
"will be searched;")
|
||||
parser.add_option("--configfile",
|
||||
action = "store", type = "string", dest = "configfile",
|
||||
default = None,
|
||||
help = "path to the config file to use "
|
||||
"[default: %default]")
|
||||
parser.add_option("--pulsefile",
|
||||
action = "store", type = "string", dest = "pulsefile",
|
||||
default = None,
|
||||
help = "path to file containing a pulse message in "
|
||||
"json format that you want to inject into the monitor")
|
||||
parser.add_option("--ignore-unused-engines",
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest="ignore_unused_engines",
|
||||
help="If defined, don't load unused engines in individual tests."
|
||||
" Has no effect for pulse monitor.")
|
||||
(options, args) = parser.parse_args()
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option("--mobile",
|
||||
action = "store_true", dest = "mobile",
|
||||
default = False,
|
||||
help = "run with mobile settings")
|
||||
parser.add_option("--testfile",
|
||||
action = "store", type = "string", dest = "testfile",
|
||||
default = '../../services/sync/tests/tps/test_sync.js',
|
||||
help = "path to the test file to run "
|
||||
"[default: %default]")
|
||||
parser.add_option("--logfile",
|
||||
action = "store", type = "string", dest = "logfile",
|
||||
default = 'tps.log',
|
||||
help = "path to the log file [default: %default]")
|
||||
parser.add_option("--resultfile",
|
||||
action = "store", type = "string", dest = "resultfile",
|
||||
default = 'tps_result.json',
|
||||
help = "path to the result file [default: %default]")
|
||||
parser.add_option("--binary",
|
||||
action = "store", type = "string", dest = "binary",
|
||||
default = None,
|
||||
help = "path to the Firefox binary, specified either as "
|
||||
"a local file or a url; if omitted, the PATH "
|
||||
"will be searched;")
|
||||
parser.add_option("--configfile",
|
||||
action = "store", type = "string", dest = "configfile",
|
||||
default = None,
|
||||
help = "path to the config file to use "
|
||||
"[default: %default]")
|
||||
parser.add_option("--pulsefile",
|
||||
action = "store", type = "string", dest = "pulsefile",
|
||||
default = None,
|
||||
help = "path to file containing a pulse message in "
|
||||
"json format that you want to inject into the monitor")
|
||||
parser.add_option("--ignore-unused-engines",
|
||||
default=False,
|
||||
action="store_true",
|
||||
dest="ignore_unused_engines",
|
||||
help="If defined, don't load unused engines in individual tests."
|
||||
" Has no effect for pulse monitor.")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
configfile = options.configfile
|
||||
if configfile is None:
|
||||
if os.environ.get('VIRTUAL_ENV'):
|
||||
configfile = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||
if configfile is None or not os.access(configfile, os.F_OK):
|
||||
raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
|
||||
"specify a config file using the --configfile option")
|
||||
configfile = options.configfile
|
||||
if configfile is None:
|
||||
if os.environ.get('VIRTUAL_ENV'):
|
||||
configfile = os.path.join(os.path.dirname(__file__), 'config.json')
|
||||
if configfile is None or not os.access(configfile, os.F_OK):
|
||||
raise Exception("Unable to find config.json in a VIRTUAL_ENV; you must "
|
||||
"specify a config file using the --configfile option")
|
||||
|
||||
# load the config file
|
||||
f = open(configfile, 'r')
|
||||
configcontent = f.read()
|
||||
f.close()
|
||||
config = json.loads(configcontent)
|
||||
# load the config file
|
||||
f = open(configfile, 'r')
|
||||
configcontent = f.read()
|
||||
f.close()
|
||||
config = json.loads(configcontent)
|
||||
|
||||
rlock = RLock()
|
||||
rlock = RLock()
|
||||
|
||||
print 'using result file', options.resultfile
|
||||
print 'using result file', options.resultfile
|
||||
|
||||
extensionDir = config.get("extensiondir")
|
||||
if not extensionDir or extensionDir == '__EXTENSIONDIR__':
|
||||
extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps")
|
||||
else:
|
||||
if sys.platform == 'win32':
|
||||
# replace msys-style paths with proper Windows paths
|
||||
import re
|
||||
m = re.match('^\/\w\/', extensionDir)
|
||||
if m:
|
||||
extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
|
||||
extensionDir = extensionDir.replace("/", "\\")
|
||||
extensionDir = config.get("extensiondir")
|
||||
if not extensionDir or extensionDir == '__EXTENSIONDIR__':
|
||||
extensionDir = os.path.join(os.getcwd(), "..", "..", "services", "sync", "tps", "extensions")
|
||||
else:
|
||||
if sys.platform == 'win32':
|
||||
# replace msys-style paths with proper Windows paths
|
||||
import re
|
||||
m = re.match('^\/\w\/', extensionDir)
|
||||
if m:
|
||||
extensionDir = "%s:/%s" % (m.group(0)[1:2], extensionDir[3:])
|
||||
extensionDir = extensionDir.replace("/", "\\")
|
||||
|
||||
TPS = TPSTestRunner(extensionDir,
|
||||
testfile=options.testfile,
|
||||
logfile=options.logfile,
|
||||
binary=options.binary,
|
||||
config=config,
|
||||
rlock=rlock,
|
||||
mobile=options.mobile,
|
||||
resultfile=options.resultfile,
|
||||
ignore_unused_engines=options.ignore_unused_engines)
|
||||
TPS.run_tests()
|
||||
TPS = TPSTestRunner(extensionDir,
|
||||
testfile=options.testfile,
|
||||
logfile=options.logfile,
|
||||
binary=options.binary,
|
||||
config=config,
|
||||
rlock=rlock,
|
||||
mobile=options.mobile,
|
||||
resultfile=options.resultfile,
|
||||
ignore_unused_engines=options.ignore_unused_engines)
|
||||
TPS.run_tests()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
@ -6,91 +6,89 @@ import copy
|
||||
import httplib2
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import mozinstall
|
||||
|
||||
from mozprocess.pid import get_pids
|
||||
from mozprofile import Profile
|
||||
from mozrunner import FirefoxRunner
|
||||
|
||||
class TPSFirefoxRunner(object):
|
||||
|
||||
PROCESS_TIMEOUT = 240
|
||||
|
||||
def __init__(self, binary):
|
||||
if binary is not None and ('http://' in binary or 'ftp://' in binary):
|
||||
self.url = binary
|
||||
self.binary = None
|
||||
else:
|
||||
self.url = None
|
||||
self.binary = binary
|
||||
self.runner = None
|
||||
self.installdir = None
|
||||
|
||||
def __del__(self):
|
||||
if self.installdir:
|
||||
shutil.rmtree(self.installdir, True)
|
||||
|
||||
def download_url(self, url, dest=None):
|
||||
h = httplib2.Http()
|
||||
resp, content = h.request(url, "GET")
|
||||
if dest == None:
|
||||
dest = os.path.basename(url)
|
||||
|
||||
local = open(dest, 'wb')
|
||||
local.write(content)
|
||||
local.close()
|
||||
return dest
|
||||
|
||||
def download_build(self, installdir='downloadedbuild', appname='firefox'):
|
||||
self.installdir = os.path.abspath(installdir)
|
||||
buildName = os.path.basename(self.url)
|
||||
pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
buildName)
|
||||
|
||||
# delete the build if it already exists
|
||||
if os.access(pathToBuild, os.F_OK):
|
||||
os.remove(pathToBuild)
|
||||
|
||||
# download the build
|
||||
print "downloading build"
|
||||
self.download_url(self.url, pathToBuild)
|
||||
|
||||
# install the build
|
||||
print "installing %s" % pathToBuild
|
||||
shutil.rmtree(self.installdir, True)
|
||||
binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
|
||||
|
||||
# remove the downloaded archive
|
||||
os.remove(pathToBuild)
|
||||
|
||||
return binary
|
||||
|
||||
def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
|
||||
"""Runs the given FirefoxRunner with the given Profile, waits
|
||||
for completion, then returns the process exit code
|
||||
"""
|
||||
if profile is None:
|
||||
profile = Profile()
|
||||
self.profile = profile
|
||||
|
||||
if self.binary is None and self.url:
|
||||
self.binary = self.download_build()
|
||||
|
||||
if self.runner is None:
|
||||
self.runner = FirefoxRunner(self.profile, binary=self.binary)
|
||||
|
||||
self.runner.profile = self.profile
|
||||
|
||||
if env is not None:
|
||||
self.runner.env.update(env)
|
||||
|
||||
if args is not None:
|
||||
self.runner.cmdargs = copy.copy(args)
|
||||
|
||||
self.runner.start()
|
||||
|
||||
status = self.runner.process_handler.waitForFinish(timeout=timeout)
|
||||
|
||||
return status
|
||||
PROCESS_TIMEOUT = 240
|
||||
|
||||
def __init__(self, binary):
|
||||
if binary is not None and ('http://' in binary or 'ftp://' in binary):
|
||||
self.url = binary
|
||||
self.binary = None
|
||||
else:
|
||||
self.url = None
|
||||
self.binary = binary
|
||||
self.runner = None
|
||||
self.installdir = None
|
||||
|
||||
def __del__(self):
|
||||
if self.installdir:
|
||||
shutil.rmtree(self.installdir, True)
|
||||
|
||||
def download_url(self, url, dest=None):
|
||||
h = httplib2.Http()
|
||||
resp, content = h.request(url, "GET")
|
||||
if dest == None:
|
||||
dest = os.path.basename(url)
|
||||
|
||||
local = open(dest, 'wb')
|
||||
local.write(content)
|
||||
local.close()
|
||||
return dest
|
||||
|
||||
def download_build(self, installdir='downloadedbuild', appname='firefox'):
|
||||
self.installdir = os.path.abspath(installdir)
|
||||
buildName = os.path.basename(self.url)
|
||||
pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
buildName)
|
||||
|
||||
# delete the build if it already exists
|
||||
if os.access(pathToBuild, os.F_OK):
|
||||
os.remove(pathToBuild)
|
||||
|
||||
# download the build
|
||||
print "downloading build"
|
||||
self.download_url(self.url, pathToBuild)
|
||||
|
||||
# install the build
|
||||
print "installing %s" % pathToBuild
|
||||
shutil.rmtree(self.installdir, True)
|
||||
binary = mozinstall.install(src=pathToBuild, dest=self.installdir)
|
||||
|
||||
# remove the downloaded archive
|
||||
os.remove(pathToBuild)
|
||||
|
||||
return binary
|
||||
|
||||
def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
|
||||
"""Runs the given FirefoxRunner with the given Profile, waits
|
||||
for completion, then returns the process exit code
|
||||
"""
|
||||
if profile is None:
|
||||
profile = Profile()
|
||||
self.profile = profile
|
||||
|
||||
if self.binary is None and self.url:
|
||||
self.binary = self.download_build()
|
||||
|
||||
if self.runner is None:
|
||||
self.runner = FirefoxRunner(self.profile, binary=self.binary)
|
||||
|
||||
self.runner.profile = self.profile
|
||||
|
||||
if env is not None:
|
||||
self.runner.env.update(env)
|
||||
|
||||
if args is not None:
|
||||
self.runner.cmdargs = copy.copy(args)
|
||||
|
||||
self.runner.start()
|
||||
|
||||
status = self.runner.process_handler.waitForFinish(timeout=timeout)
|
||||
|
||||
return status
|
||||
|
@ -18,10 +18,10 @@ DOCROOT = '.'
|
||||
|
||||
class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
||||
allow_reuse_address = True
|
||||
|
||||
|
||||
class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
def translate_path(self, path):
|
||||
# It appears that the default path is '/' and os.path.join makes the '/'
|
||||
# It appears that the default path is '/' and os.path.join makes the '/'
|
||||
o = urlparse(path)
|
||||
|
||||
sep = '/'
|
||||
@ -92,9 +92,9 @@ class MozHttpd(object):
|
||||
for fileName in fileList:
|
||||
if fileName == webline:
|
||||
found = True
|
||||
|
||||
|
||||
if (found == False):
|
||||
print "NOT FOUND: " + webline.strip()
|
||||
print "NOT FOUND: " + webline.strip()
|
||||
|
||||
def stop(self):
|
||||
if self.httpd:
|
||||
@ -102,4 +102,3 @@ class MozHttpd(object):
|
||||
self.httpd.server_close()
|
||||
|
||||
__del__ = stop
|
||||
|
||||
|
@ -2,76 +2,74 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
class TPSTestPhase(object):
|
||||
|
||||
lineRe = re.compile(
|
||||
r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
|
||||
lineRe = re.compile(
|
||||
r"^(.*?)test phase (?P<matchphase>\d+): (?P<matchstatus>.*)$")
|
||||
|
||||
def __init__(self, phase, profile, testname, testpath, logfile, env,
|
||||
firefoxRunner, logfn, ignore_unused_engines=False):
|
||||
self.phase = phase
|
||||
self.profile = profile
|
||||
self.testname = str(testname) # this might be passed in as unicode
|
||||
self.testpath = testpath
|
||||
self.logfile = logfile
|
||||
self.env = env
|
||||
self.firefoxRunner = firefoxRunner
|
||||
self.log = logfn
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self._status = None
|
||||
self.errline = ''
|
||||
def __init__(self, phase, profile, testname, testpath, logfile, env,
|
||||
firefoxRunner, logfn, ignore_unused_engines=False):
|
||||
self.phase = phase
|
||||
self.profile = profile
|
||||
self.testname = str(testname) # this might be passed in as unicode
|
||||
self.testpath = testpath
|
||||
self.logfile = logfile
|
||||
self.env = env
|
||||
self.firefoxRunner = firefoxRunner
|
||||
self.log = logfn
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self._status = None
|
||||
self.errline = ''
|
||||
|
||||
@property
|
||||
def phasenum(self):
|
||||
match = re.match('.*?(\d+)', self.phase)
|
||||
if match:
|
||||
return match.group(1)
|
||||
@property
|
||||
def phasenum(self):
|
||||
match = re.match('.*?(\d+)', self.phase)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
return self._status if self._status else 'unknown'
|
||||
@property
|
||||
def status(self):
|
||||
return self._status if self._status else 'unknown'
|
||||
|
||||
def run(self):
|
||||
# launch Firefox
|
||||
args = [ '-tps', self.testpath,
|
||||
'-tpsphase', self.phasenum,
|
||||
'-tpslogfile', self.logfile ]
|
||||
def run(self):
|
||||
# launch Firefox
|
||||
args = [ '-tps', self.testpath,
|
||||
'-tpsphase', self.phasenum,
|
||||
'-tpslogfile', self.logfile ]
|
||||
|
||||
if self.ignore_unused_engines:
|
||||
args.append('--ignore-unused-engines')
|
||||
if self.ignore_unused_engines:
|
||||
args.append('--ignore-unused-engines')
|
||||
|
||||
self.log("\nlaunching Firefox for phase %s with args %s\n" %
|
||||
(self.phase, str(args)))
|
||||
returncode = self.firefoxRunner.run(env=self.env,
|
||||
args=args,
|
||||
profile=self.profile)
|
||||
self.log("\nlaunching Firefox for phase %s with args %s\n" %
|
||||
(self.phase, str(args)))
|
||||
self.firefoxRunner.run(env=self.env,
|
||||
args=args,
|
||||
profile=self.profile)
|
||||
|
||||
# parse the logfile and look for results from the current test phase
|
||||
found_test = False
|
||||
f = open(self.logfile, 'r')
|
||||
for line in f:
|
||||
# parse the logfile and look for results from the current test phase
|
||||
found_test = False
|
||||
f = open(self.logfile, 'r')
|
||||
for line in f:
|
||||
|
||||
# skip to the part of the log file that deals with the test we're running
|
||||
if not found_test:
|
||||
if line.find("Running test %s" % self.testname) > -1:
|
||||
found_test = True
|
||||
else:
|
||||
continue
|
||||
# skip to the part of the log file that deals with the test we're running
|
||||
if not found_test:
|
||||
if line.find("Running test %s" % self.testname) > -1:
|
||||
found_test = True
|
||||
else:
|
||||
continue
|
||||
|
||||
# look for the status of the current phase
|
||||
match = self.lineRe.match(line)
|
||||
if match:
|
||||
if match.group("matchphase") == self.phasenum:
|
||||
self._status = match.group("matchstatus")
|
||||
break
|
||||
# look for the status of the current phase
|
||||
match = self.lineRe.match(line)
|
||||
if match:
|
||||
if match.group("matchphase") == self.phasenum:
|
||||
self._status = match.group("matchstatus")
|
||||
break
|
||||
|
||||
# set the status to FAIL if there is TPS error
|
||||
if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
|
||||
self._status = "FAIL"
|
||||
self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
|
||||
|
||||
f.close()
|
||||
# set the status to FAIL if there is TPS error
|
||||
if line.find("CROSSWEAVE ERROR: ") > -1 and not self._status:
|
||||
self._status = "FAIL"
|
||||
self.errline = line[line.find("CROSSWEAVE ERROR: ") + len("CROSSWEAVE ERROR: "):]
|
||||
|
||||
f.close()
|
||||
|
@ -2,19 +2,14 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import httplib
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import random
|
||||
import re
|
||||
import socket
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
import urllib
|
||||
|
||||
from threading import RLock
|
||||
|
||||
from mozprofile import Profile
|
||||
|
||||
@ -23,413 +18,413 @@ from tps.phase import TPSTestPhase
|
||||
from tps.mozhttpd import MozHttpd
|
||||
|
||||
class TempFile(object):
|
||||
"""Class for temporary files that delete themselves when garbage-collected.
|
||||
"""
|
||||
"""Class for temporary files that delete themselves when garbage-collected.
|
||||
"""
|
||||
|
||||
def __init__(self, prefix=None):
|
||||
self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
|
||||
def __init__(self, prefix=None):
|
||||
self.fd, self.filename = self.tmpfile = tempfile.mkstemp(prefix=prefix)
|
||||
|
||||
def write(self, data):
|
||||
if self.fd:
|
||||
os.write(self.fd, data)
|
||||
def write(self, data):
|
||||
if self.fd:
|
||||
os.write(self.fd, data)
|
||||
|
||||
def close(self):
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
def close(self):
|
||||
if self.fd:
|
||||
os.close(self.fd)
|
||||
self.fd = None
|
||||
|
||||
def cleanup(self):
|
||||
if self.fd:
|
||||
self.close()
|
||||
if os.access(self.filename, os.F_OK):
|
||||
os.remove(self.filename)
|
||||
def cleanup(self):
|
||||
if self.fd:
|
||||
self.close()
|
||||
if os.access(self.filename, os.F_OK):
|
||||
os.remove(self.filename)
|
||||
|
||||
__del__ = cleanup
|
||||
__del__ = cleanup
|
||||
|
||||
class TPSTestRunner(object):
|
||||
|
||||
default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
|
||||
'GNOME_DISABLE_CRASH_DIALOG': '1',
|
||||
'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
|
||||
'MOZ_NO_REMOTE': '1',
|
||||
'XPCOM_DEBUG_BREAK': 'warn',
|
||||
}
|
||||
default_preferences = { 'app.update.enabled' : False,
|
||||
'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
|
||||
'extensions.update.enabled' : False,
|
||||
'extensions.update.notifyUser' : False,
|
||||
'browser.shell.checkDefaultBrowser' : False,
|
||||
'browser.tabs.warnOnClose' : False,
|
||||
'browser.warnOnQuit': False,
|
||||
'browser.sessionstore.resume_from_crash': False,
|
||||
'services.sync.addons.ignoreRepositoryChecking': True,
|
||||
'services.sync.firstSync': 'notReady',
|
||||
'services.sync.lastversion': '1.0',
|
||||
'services.sync.log.rootLogger': 'Trace',
|
||||
'services.sync.log.logger.engine.addons': 'Trace',
|
||||
'services.sync.log.logger.service.main': 'Trace',
|
||||
'services.sync.log.logger.engine.bookmarks': 'Trace',
|
||||
'services.sync.log.appender.console': 'Trace',
|
||||
'services.sync.log.appender.debugLog.enabled': True,
|
||||
'toolkit.startup.max_resumed_crashes': -1,
|
||||
'browser.dom.window.dump.enabled': True,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
'extensions.update.notifyUser' : False,
|
||||
}
|
||||
syncVerRe = re.compile(
|
||||
r"Sync version: (?P<syncversion>.*)\n")
|
||||
ffVerRe = re.compile(
|
||||
r"Firefox version: (?P<ffver>.*)\n")
|
||||
ffDateRe = re.compile(
|
||||
r"Firefox builddate: (?P<ffdate>.*)\n")
|
||||
default_env = { 'MOZ_CRASHREPORTER_DISABLE': '1',
|
||||
'GNOME_DISABLE_CRASH_DIALOG': '1',
|
||||
'XRE_NO_WINDOWS_CRASH_DIALOG': '1',
|
||||
'MOZ_NO_REMOTE': '1',
|
||||
'XPCOM_DEBUG_BREAK': 'warn',
|
||||
}
|
||||
default_preferences = { 'app.update.enabled' : False,
|
||||
'extensions.getAddons.get.url': 'http://127.0.0.1:4567/en-US/firefox/api/%API_VERSION%/search/guid:%IDS%',
|
||||
'extensions.update.enabled' : False,
|
||||
'extensions.update.notifyUser' : False,
|
||||
'browser.shell.checkDefaultBrowser' : False,
|
||||
'browser.tabs.warnOnClose' : False,
|
||||
'browser.warnOnQuit': False,
|
||||
'browser.sessionstore.resume_from_crash': False,
|
||||
'services.sync.addons.ignoreRepositoryChecking': True,
|
||||
'services.sync.firstSync': 'notReady',
|
||||
'services.sync.lastversion': '1.0',
|
||||
'services.sync.log.rootLogger': 'Trace',
|
||||
'services.sync.log.logger.engine.addons': 'Trace',
|
||||
'services.sync.log.logger.service.main': 'Trace',
|
||||
'services.sync.log.logger.engine.bookmarks': 'Trace',
|
||||
'services.sync.log.appender.console': 'Trace',
|
||||
'services.sync.log.appender.debugLog.enabled': True,
|
||||
'toolkit.startup.max_resumed_crashes': -1,
|
||||
'browser.dom.window.dump.enabled': True,
|
||||
# Allow installing extensions dropped into the profile folder
|
||||
'extensions.autoDisableScopes': 10,
|
||||
# Don't open a dialog to show available add-on updates
|
||||
'extensions.update.notifyUser' : False,
|
||||
}
|
||||
syncVerRe = re.compile(
|
||||
r"Sync version: (?P<syncversion>.*)\n")
|
||||
ffVerRe = re.compile(
|
||||
r"Firefox version: (?P<ffver>.*)\n")
|
||||
ffDateRe = re.compile(
|
||||
r"Firefox builddate: (?P<ffdate>.*)\n")
|
||||
|
||||
def __init__(self, extensionDir,
|
||||
testfile="sync.test",
|
||||
binary=None, config=None, rlock=None, mobile=False,
|
||||
logfile="tps.log", resultfile="tps_result.json",
|
||||
ignore_unused_engines=False):
|
||||
self.extensions = []
|
||||
self.testfile = testfile
|
||||
self.logfile = os.path.abspath(logfile)
|
||||
self.resultfile = resultfile
|
||||
self.binary = binary
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self.config = config if config else {}
|
||||
self.repo = None
|
||||
self.changeset = None
|
||||
self.branch = None
|
||||
self.numfailed = 0
|
||||
self.numpassed = 0
|
||||
self.nightly = False
|
||||
self.rlock = rlock
|
||||
self.mobile = mobile
|
||||
self.tpsxpi = None
|
||||
self.firefoxRunner = None
|
||||
self.extensionDir = extensionDir
|
||||
self.productversion = None
|
||||
self.addonversion = None
|
||||
self.postdata = {}
|
||||
self.errorlogs = {}
|
||||
def __init__(self, extensionDir,
|
||||
testfile="sync.test",
|
||||
binary=None, config=None, rlock=None, mobile=False,
|
||||
logfile="tps.log", resultfile="tps_result.json",
|
||||
ignore_unused_engines=False):
|
||||
self.extensions = []
|
||||
self.testfile = testfile
|
||||
self.logfile = os.path.abspath(logfile)
|
||||
self.resultfile = resultfile
|
||||
self.binary = binary
|
||||
self.ignore_unused_engines = ignore_unused_engines
|
||||
self.config = config if config else {}
|
||||
self.repo = None
|
||||
self.changeset = None
|
||||
self.branch = None
|
||||
self.numfailed = 0
|
||||
self.numpassed = 0
|
||||
self.nightly = False
|
||||
self.rlock = rlock
|
||||
self.mobile = mobile
|
||||
self.tpsxpi = None
|
||||
self.firefoxRunner = None
|
||||
self.extensionDir = extensionDir
|
||||
self.productversion = None
|
||||
self.addonversion = None
|
||||
self.postdata = {}
|
||||
self.errorlogs = {}
|
||||
|
||||
@property
|
||||
def mobile(self):
|
||||
return self._mobile
|
||||
@property
|
||||
def mobile(self):
|
||||
return self._mobile
|
||||
|
||||
@mobile.setter
|
||||
def mobile(self, value):
|
||||
self._mobile = value
|
||||
self.synctype = 'desktop' if not self._mobile else 'mobile'
|
||||
@mobile.setter
|
||||
def mobile(self, value):
|
||||
self._mobile = value
|
||||
self.synctype = 'desktop' if not self._mobile else 'mobile'
|
||||
|
||||
def log(self, msg, printToConsole=False):
|
||||
"""Appends a string to the logfile"""
|
||||
def log(self, msg, printToConsole=False):
|
||||
"""Appends a string to the logfile"""
|
||||
|
||||
f = open(self.logfile, 'a')
|
||||
f.write(msg)
|
||||
f.close()
|
||||
if printToConsole:
|
||||
print msg
|
||||
f = open(self.logfile, 'a')
|
||||
f.write(msg)
|
||||
f.close()
|
||||
if printToConsole:
|
||||
print msg
|
||||
|
||||
def writeToResultFile(self, postdata, body=None,
|
||||
sendTo=['crossweave@mozilla.com']):
|
||||
"""Writes results to test file"""
|
||||
def writeToResultFile(self, postdata, body=None,
|
||||
sendTo=['crossweave@mozilla.com']):
|
||||
"""Writes results to test file"""
|
||||
|
||||
results = {'results': []}
|
||||
results = {'results': []}
|
||||
|
||||
if os.access(self.resultfile, os.F_OK):
|
||||
f = open(self.resultfile, 'r')
|
||||
results = json.loads(f.read())
|
||||
f.close()
|
||||
if os.access(self.resultfile, os.F_OK):
|
||||
f = open(self.resultfile, 'r')
|
||||
results = json.loads(f.read())
|
||||
f.close()
|
||||
|
||||
f = open(self.resultfile, 'w')
|
||||
if body is not None:
|
||||
postdata['body'] = body
|
||||
if self.numpassed is not None:
|
||||
postdata['numpassed'] = self.numpassed
|
||||
if self.numfailed is not None:
|
||||
postdata['numfailed'] = self.numfailed
|
||||
if self.firefoxRunner and self.firefoxRunner.url:
|
||||
postdata['firefoxrunnerurl'] = self.firefoxRunner.url
|
||||
f = open(self.resultfile, 'w')
|
||||
if body is not None:
|
||||
postdata['body'] = body
|
||||
if self.numpassed is not None:
|
||||
postdata['numpassed'] = self.numpassed
|
||||
if self.numfailed is not None:
|
||||
postdata['numfailed'] = self.numfailed
|
||||
if self.firefoxRunner and self.firefoxRunner.url:
|
||||
postdata['firefoxrunnerurl'] = self.firefoxRunner.url
|
||||
|
||||
postdata['sendTo'] = sendTo
|
||||
results['results'].append(postdata)
|
||||
f.write(json.dumps(results, indent=2))
|
||||
f.close()
|
||||
postdata['sendTo'] = sendTo
|
||||
results['results'].append(postdata)
|
||||
f.write(json.dumps(results, indent=2))
|
||||
f.close()
|
||||
|
||||
def _zip_add_file(self, zip, file, rootDir):
|
||||
zip.write(os.path.join(rootDir, file), file)
|
||||
def _zip_add_file(self, zip, file, rootDir):
|
||||
zip.write(os.path.join(rootDir, file), file)
|
||||
|
||||
def _zip_add_dir(self, zip, dir, rootDir):
|
||||
try:
|
||||
zip.write(os.path.join(rootDir, dir), dir)
|
||||
except:
|
||||
# on some OS's, adding directory entries doesn't seem to work
|
||||
pass
|
||||
for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
|
||||
for f in files:
|
||||
zip.write(os.path.join(root, f), os.path.join(dir, f))
|
||||
|
||||
def run_single_test(self, testdir, testname):
|
||||
testpath = os.path.join(testdir, testname)
|
||||
self.log("Running test %s\n" % testname)
|
||||
|
||||
# Create a random account suffix that is used when creating test
|
||||
# accounts on a staging server.
|
||||
account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
|
||||
for i in range(1,6)])}
|
||||
self.config['account'].update(account_suffix)
|
||||
|
||||
# Read and parse the test file, merge it with the contents of the config
|
||||
# file, and write the combined output to a temporary file.
|
||||
f = open(testpath, 'r')
|
||||
testcontent = f.read()
|
||||
f.close()
|
||||
try:
|
||||
test = json.loads(testcontent)
|
||||
except:
|
||||
test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
|
||||
|
||||
testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
|
||||
testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
|
||||
|
||||
tmpfile = TempFile(prefix='tps_test_')
|
||||
tmpfile.write(testcontent)
|
||||
tmpfile.close()
|
||||
|
||||
# generate the profiles defined in the test, and a list of test phases
|
||||
profiles = {}
|
||||
phaselist = []
|
||||
for phase in test:
|
||||
profilename = test[phase]
|
||||
|
||||
# create the profile if necessary
|
||||
if not profilename in profiles:
|
||||
profiles[profilename] = Profile(preferences = self.preferences,
|
||||
addons = self.extensions)
|
||||
|
||||
# create the test phase
|
||||
phaselist.append(TPSTestPhase(
|
||||
phase,
|
||||
profiles[profilename],
|
||||
testname,
|
||||
tmpfile.filename,
|
||||
self.logfile,
|
||||
self.env,
|
||||
self.firefoxRunner,
|
||||
self.log,
|
||||
ignore_unused_engines=self.ignore_unused_engines))
|
||||
|
||||
# sort the phase list by name
|
||||
phaselist = sorted(phaselist, key=lambda phase: phase.phase)
|
||||
|
||||
# run each phase in sequence, aborting at the first failure
|
||||
for phase in phaselist:
|
||||
phase.run()
|
||||
|
||||
# if a failure occurred, dump the entire sync log into the test log
|
||||
if phase.status != "PASS":
|
||||
for profile in profiles:
|
||||
self.log("\nDumping sync log for profile %s\n" % profiles[profile].profile)
|
||||
for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
|
||||
for f in files:
|
||||
weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
|
||||
if os.access(weavelog, os.F_OK):
|
||||
with open(weavelog, 'r') as fh:
|
||||
for line in fh:
|
||||
possible_time = line[0:13]
|
||||
if len(possible_time) == 13 and possible_time.isdigit():
|
||||
time_ms = int(possible_time)
|
||||
formatted = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time_ms / 1000))
|
||||
self.log('%s.%03d %s' % (
|
||||
formatted, time_ms % 1000, line[14:] ))
|
||||
else:
|
||||
self.log(line)
|
||||
break;
|
||||
|
||||
# grep the log for FF and sync versions
|
||||
f = open(self.logfile)
|
||||
logdata = f.read()
|
||||
match = self.syncVerRe.search(logdata)
|
||||
sync_version = match.group("syncversion") if match else 'unknown'
|
||||
match = self.ffVerRe.search(logdata)
|
||||
firefox_version = match.group("ffver") if match else 'unknown'
|
||||
match = self.ffDateRe.search(logdata)
|
||||
firefox_builddate = match.group("ffdate") if match else 'unknown'
|
||||
f.close()
|
||||
if phase.status == 'PASS':
|
||||
logdata = ''
|
||||
else:
|
||||
# we only care about the log data for this specific test
|
||||
logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
|
||||
|
||||
result = {
|
||||
'PASS': lambda x: ('TEST-PASS', ''),
|
||||
'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
|
||||
'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
|
||||
} [phase.status](phase.errline)
|
||||
logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
|
||||
|
||||
try:
|
||||
repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
|
||||
except:
|
||||
repoinfo = {}
|
||||
apprepo = repoinfo.get('application_repository', '')
|
||||
appchangeset = repoinfo.get('application_changeset', '')
|
||||
|
||||
# save logdata to a temporary file for posting to the db
|
||||
tmplogfile = None
|
||||
if logdata:
|
||||
tmplogfile = TempFile(prefix='tps_log_')
|
||||
tmplogfile.write(logdata)
|
||||
tmplogfile.close()
|
||||
self.errorlogs[testname] = tmplogfile
|
||||
|
||||
resultdata = ({ "productversion": { "version": firefox_version,
|
||||
"buildid": firefox_builddate,
|
||||
"builddate": firefox_builddate[0:8],
|
||||
"product": "Firefox",
|
||||
"repository": apprepo,
|
||||
"changeset": appchangeset,
|
||||
},
|
||||
"addonversion": { "version": sync_version,
|
||||
"product": "Firefox Sync" },
|
||||
"name": testname,
|
||||
"message": result[1],
|
||||
"state": result[0],
|
||||
"logdata": logdata
|
||||
})
|
||||
|
||||
self.log(logstr, True)
|
||||
for phase in phaselist:
|
||||
print "\t%s: %s" % (phase.phase, phase.status)
|
||||
if phase.status == 'FAIL':
|
||||
break
|
||||
|
||||
return resultdata
|
||||
|
||||
def run_tests(self):
|
||||
# delete the logfile if it already exists
|
||||
if os.access(self.logfile, os.F_OK):
|
||||
os.remove(self.logfile)
|
||||
|
||||
# Make a copy of the default env variables and preferences, and update
|
||||
# them for mobile settings if needed.
|
||||
self.env = self.default_env.copy()
|
||||
self.preferences = self.default_preferences.copy()
|
||||
if self.mobile:
|
||||
self.preferences.update({'services.sync.client.type' : 'mobile'})
|
||||
|
||||
# Acquire a lock to make sure no other threads are running tests
|
||||
# at the same time.
|
||||
if self.rlock:
|
||||
self.rlock.acquire()
|
||||
|
||||
try:
|
||||
# Create the Firefox runner, which will download and install the
|
||||
# build, as needed.
|
||||
if not self.firefoxRunner:
|
||||
self.firefoxRunner = TPSFirefoxRunner(self.binary)
|
||||
|
||||
# now, run the test group
|
||||
self.run_test_group()
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.numpassed = 0
|
||||
self.numfailed = 1
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
try:
|
||||
|
||||
if self.numfailed > 0 or self.numpassed == 0:
|
||||
To = self.config['email'].get('notificationlist')
|
||||
else:
|
||||
To = self.config['email'].get('passednotificationlist')
|
||||
self.writeToResultFile(self.postdata,
|
||||
sendTo=To)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
def _zip_add_dir(self, zip, dir, rootDir):
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
zip.write(os.path.join(rootDir, dir), dir)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
# on some OS's, adding directory entries doesn't seem to work
|
||||
pass
|
||||
for root, dirs, files in os.walk(os.path.join(rootDir, dir)):
|
||||
for f in files:
|
||||
zip.write(os.path.join(root, f), os.path.join(dir, f))
|
||||
|
||||
# release our lock
|
||||
if self.rlock:
|
||||
self.rlock.release()
|
||||
def run_single_test(self, testdir, testname):
|
||||
testpath = os.path.join(testdir, testname)
|
||||
self.log("Running test %s\n" % testname)
|
||||
|
||||
# dump out a summary of test results
|
||||
print 'Test Summary\n'
|
||||
for test in self.postdata.get('tests', {}):
|
||||
print '%s | %s | %s' % (test['state'], test['name'], test['message'])
|
||||
# Create a random account suffix that is used when creating test
|
||||
# accounts on a staging server.
|
||||
account_suffix = {"account-suffix": ''.join([str(random.randint(0,9))
|
||||
for i in range(1,6)])}
|
||||
self.config['account'].update(account_suffix)
|
||||
|
||||
def run_test_group(self):
|
||||
self.results = []
|
||||
self.extensions = []
|
||||
# Read and parse the test file, merge it with the contents of the config
|
||||
# file, and write the combined output to a temporary file.
|
||||
f = open(testpath, 'r')
|
||||
testcontent = f.read()
|
||||
f.close()
|
||||
try:
|
||||
test = json.loads(testcontent)
|
||||
except:
|
||||
test = json.loads(testcontent[testcontent.find("{"):testcontent.find("}") + 1])
|
||||
|
||||
# set the OS we're running on
|
||||
os_string = platform.uname()[2] + " " + platform.uname()[3]
|
||||
if os_string.find("Darwin") > -1:
|
||||
os_string = "Mac OS X " + platform.mac_ver()[0]
|
||||
if platform.uname()[0].find("Linux") > -1:
|
||||
os_string = "Linux " + platform.uname()[5]
|
||||
if platform.uname()[0].find("Win") > -1:
|
||||
os_string = "Windows " + platform.uname()[3]
|
||||
testcontent += 'var config = %s;\n' % json.dumps(self.config, indent=2)
|
||||
testcontent += 'var seconds_since_epoch = %d;\n' % int(time.time())
|
||||
|
||||
# reset number of passed/failed tests
|
||||
self.numpassed = 0
|
||||
self.numfailed = 0
|
||||
tmpfile = TempFile(prefix='tps_test_')
|
||||
tmpfile.write(testcontent)
|
||||
tmpfile.close()
|
||||
|
||||
# build our tps.xpi extension
|
||||
self.extensions.append(os.path.join(self.extensionDir, 'tps'))
|
||||
self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
|
||||
# generate the profiles defined in the test, and a list of test phases
|
||||
profiles = {}
|
||||
phaselist = []
|
||||
for phase in test:
|
||||
profilename = test[phase]
|
||||
|
||||
# build the test list
|
||||
try:
|
||||
f = open(self.testfile)
|
||||
jsondata = f.read()
|
||||
f.close()
|
||||
testfiles = json.loads(jsondata)
|
||||
testlist = testfiles['tests']
|
||||
except ValueError:
|
||||
testlist = [os.path.basename(self.testfile)]
|
||||
testdir = os.path.dirname(self.testfile)
|
||||
# create the profile if necessary
|
||||
if not profilename in profiles:
|
||||
profiles[profilename] = Profile(preferences = self.preferences,
|
||||
addons = self.extensions)
|
||||
|
||||
self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
|
||||
self.mozhttpd.start()
|
||||
# create the test phase
|
||||
phaselist.append(TPSTestPhase(
|
||||
phase,
|
||||
profiles[profilename],
|
||||
testname,
|
||||
tmpfile.filename,
|
||||
self.logfile,
|
||||
self.env,
|
||||
self.firefoxRunner,
|
||||
self.log,
|
||||
ignore_unused_engines=self.ignore_unused_engines))
|
||||
|
||||
# run each test, and save the results
|
||||
for test in testlist:
|
||||
result = self.run_single_test(testdir, test)
|
||||
# sort the phase list by name
|
||||
phaselist = sorted(phaselist, key=lambda phase: phase.phase)
|
||||
|
||||
if not self.productversion:
|
||||
self.productversion = result['productversion']
|
||||
if not self.addonversion:
|
||||
self.addonversion = result['addonversion']
|
||||
# run each phase in sequence, aborting at the first failure
|
||||
for phase in phaselist:
|
||||
phase.run()
|
||||
|
||||
self.results.append({'state': result['state'],
|
||||
'name': result['name'],
|
||||
'message': result['message'],
|
||||
'logdata': result['logdata']})
|
||||
if result['state'] == 'TEST-PASS':
|
||||
self.numpassed += 1
|
||||
else:
|
||||
self.numfailed += 1
|
||||
# if a failure occurred, dump the entire sync log into the test log
|
||||
if phase.status != "PASS":
|
||||
for profile in profiles:
|
||||
self.log("\nDumping sync log for profile %s\n" % profiles[profile].profile)
|
||||
for root, dirs, files in os.walk(os.path.join(profiles[profile].profile, 'weave', 'logs')):
|
||||
for f in files:
|
||||
weavelog = os.path.join(profiles[profile].profile, 'weave', 'logs', f)
|
||||
if os.access(weavelog, os.F_OK):
|
||||
with open(weavelog, 'r') as fh:
|
||||
for line in fh:
|
||||
possible_time = line[0:13]
|
||||
if len(possible_time) == 13 and possible_time.isdigit():
|
||||
time_ms = int(possible_time)
|
||||
formatted = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||
time.localtime(time_ms / 1000))
|
||||
self.log('%s.%03d %s' % (
|
||||
formatted, time_ms % 1000, line[14:] ))
|
||||
else:
|
||||
self.log(line)
|
||||
break;
|
||||
|
||||
self.mozhttpd.stop()
|
||||
# grep the log for FF and sync versions
|
||||
f = open(self.logfile)
|
||||
logdata = f.read()
|
||||
match = self.syncVerRe.search(logdata)
|
||||
sync_version = match.group("syncversion") if match else 'unknown'
|
||||
match = self.ffVerRe.search(logdata)
|
||||
firefox_version = match.group("ffver") if match else 'unknown'
|
||||
match = self.ffDateRe.search(logdata)
|
||||
firefox_builddate = match.group("ffdate") if match else 'unknown'
|
||||
f.close()
|
||||
if phase.status == 'PASS':
|
||||
logdata = ''
|
||||
else:
|
||||
# we only care about the log data for this specific test
|
||||
logdata = logdata[logdata.find('Running test %s' % (str(testname))):]
|
||||
|
||||
# generate the postdata we'll use to post the results to the db
|
||||
self.postdata = { 'tests': self.results,
|
||||
'os':os_string,
|
||||
'testtype': 'crossweave',
|
||||
'productversion': self.productversion,
|
||||
'addonversion': self.addonversion,
|
||||
'synctype': self.synctype,
|
||||
}
|
||||
result = {
|
||||
'PASS': lambda x: ('TEST-PASS', ''),
|
||||
'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
|
||||
'unknown': lambda x: ('TEST-UNEXPECTED-FAIL', 'test did not complete')
|
||||
} [phase.status](phase.errline)
|
||||
logstr = "\n%s | %s%s\n" % (result[0], testname, (' | %s' % result[1] if result[1] else ''))
|
||||
|
||||
try:
|
||||
repoinfo = self.firefoxRunner.runner.get_repositoryInfo()
|
||||
except:
|
||||
repoinfo = {}
|
||||
apprepo = repoinfo.get('application_repository', '')
|
||||
appchangeset = repoinfo.get('application_changeset', '')
|
||||
|
||||
# save logdata to a temporary file for posting to the db
|
||||
tmplogfile = None
|
||||
if logdata:
|
||||
tmplogfile = TempFile(prefix='tps_log_')
|
||||
tmplogfile.write(logdata)
|
||||
tmplogfile.close()
|
||||
self.errorlogs[testname] = tmplogfile
|
||||
|
||||
resultdata = ({ "productversion": { "version": firefox_version,
|
||||
"buildid": firefox_builddate,
|
||||
"builddate": firefox_builddate[0:8],
|
||||
"product": "Firefox",
|
||||
"repository": apprepo,
|
||||
"changeset": appchangeset,
|
||||
},
|
||||
"addonversion": { "version": sync_version,
|
||||
"product": "Firefox Sync" },
|
||||
"name": testname,
|
||||
"message": result[1],
|
||||
"state": result[0],
|
||||
"logdata": logdata
|
||||
})
|
||||
|
||||
self.log(logstr, True)
|
||||
for phase in phaselist:
|
||||
print "\t%s: %s" % (phase.phase, phase.status)
|
||||
if phase.status == 'FAIL':
|
||||
break
|
||||
|
||||
return resultdata
|
||||
|
||||
def run_tests(self):
|
||||
# delete the logfile if it already exists
|
||||
if os.access(self.logfile, os.F_OK):
|
||||
os.remove(self.logfile)
|
||||
|
||||
# Make a copy of the default env variables and preferences, and update
|
||||
# them for mobile settings if needed.
|
||||
self.env = self.default_env.copy()
|
||||
self.preferences = self.default_preferences.copy()
|
||||
if self.mobile:
|
||||
self.preferences.update({'services.sync.client.type' : 'mobile'})
|
||||
|
||||
# Acquire a lock to make sure no other threads are running tests
|
||||
# at the same time.
|
||||
if self.rlock:
|
||||
self.rlock.acquire()
|
||||
|
||||
try:
|
||||
# Create the Firefox runner, which will download and install the
|
||||
# build, as needed.
|
||||
if not self.firefoxRunner:
|
||||
self.firefoxRunner = TPSFirefoxRunner(self.binary)
|
||||
|
||||
# now, run the test group
|
||||
self.run_test_group()
|
||||
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.numpassed = 0
|
||||
self.numfailed = 1
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
else:
|
||||
try:
|
||||
|
||||
if self.numfailed > 0 or self.numpassed == 0:
|
||||
To = self.config['email'].get('notificationlist')
|
||||
else:
|
||||
To = self.config['email'].get('passednotificationlist')
|
||||
self.writeToResultFile(self.postdata,
|
||||
sendTo=To)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
try:
|
||||
self.writeToResultFile(self.postdata,
|
||||
'<pre>%s</pre>' % traceback.format_exc())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
# release our lock
|
||||
if self.rlock:
|
||||
self.rlock.release()
|
||||
|
||||
# dump out a summary of test results
|
||||
print 'Test Summary\n'
|
||||
for test in self.postdata.get('tests', {}):
|
||||
print '%s | %s | %s' % (test['state'], test['name'], test['message'])
|
||||
|
||||
def run_test_group(self):
|
||||
self.results = []
|
||||
self.extensions = []
|
||||
|
||||
# set the OS we're running on
|
||||
os_string = platform.uname()[2] + " " + platform.uname()[3]
|
||||
if os_string.find("Darwin") > -1:
|
||||
os_string = "Mac OS X " + platform.mac_ver()[0]
|
||||
if platform.uname()[0].find("Linux") > -1:
|
||||
os_string = "Linux " + platform.uname()[5]
|
||||
if platform.uname()[0].find("Win") > -1:
|
||||
os_string = "Windows " + platform.uname()[3]
|
||||
|
||||
# reset number of passed/failed tests
|
||||
self.numpassed = 0
|
||||
self.numfailed = 0
|
||||
|
||||
# build our tps.xpi extension
|
||||
self.extensions.append(os.path.join(self.extensionDir, 'tps'))
|
||||
self.extensions.append(os.path.join(self.extensionDir, "mozmill"))
|
||||
|
||||
# build the test list
|
||||
try:
|
||||
f = open(self.testfile)
|
||||
jsondata = f.read()
|
||||
f.close()
|
||||
testfiles = json.loads(jsondata)
|
||||
testlist = testfiles['tests']
|
||||
except ValueError:
|
||||
testlist = [os.path.basename(self.testfile)]
|
||||
testdir = os.path.dirname(self.testfile)
|
||||
|
||||
self.mozhttpd = MozHttpd(port=4567, docroot=testdir)
|
||||
self.mozhttpd.start()
|
||||
|
||||
# run each test, and save the results
|
||||
for test in testlist:
|
||||
result = self.run_single_test(testdir, test)
|
||||
|
||||
if not self.productversion:
|
||||
self.productversion = result['productversion']
|
||||
if not self.addonversion:
|
||||
self.addonversion = result['addonversion']
|
||||
|
||||
self.results.append({'state': result['state'],
|
||||
'name': result['name'],
|
||||
'message': result['message'],
|
||||
'logdata': result['logdata']})
|
||||
if result['state'] == 'TEST-PASS':
|
||||
self.numpassed += 1
|
||||
else:
|
||||
self.numfailed += 1
|
||||
|
||||
self.mozhttpd.stop()
|
||||
|
||||
# generate the postdata we'll use to post the results to the db
|
||||
self.postdata = { 'tests': self.results,
|
||||
'os':os_string,
|
||||
'testtype': 'crossweave',
|
||||
'productversion': self.productversion,
|
||||
'addonversion': self.addonversion,
|
||||
'synctype': self.synctype,
|
||||
}
|
||||
|
@ -8,57 +8,57 @@ from testrunner import TPSTestRunner
|
||||
|
||||
class TPSTestThread(Thread):
|
||||
|
||||
def __init__(self, extensionDir, builddata=None,
|
||||
testfile=None, logfile=None, rlock=None, config=None):
|
||||
assert(builddata)
|
||||
assert(config)
|
||||
self.extensionDir = extensionDir
|
||||
self.builddata = builddata
|
||||
self.testfile = testfile
|
||||
self.logfile = logfile
|
||||
self.rlock = rlock
|
||||
self.config = config
|
||||
Thread.__init__(self)
|
||||
def __init__(self, extensionDir, builddata=None,
|
||||
testfile=None, logfile=None, rlock=None, config=None):
|
||||
assert(builddata)
|
||||
assert(config)
|
||||
self.extensionDir = extensionDir
|
||||
self.builddata = builddata
|
||||
self.testfile = testfile
|
||||
self.logfile = logfile
|
||||
self.rlock = rlock
|
||||
self.config = config
|
||||
Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
# run the tests in normal mode ...
|
||||
TPS = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=self.builddata['buildurl'],
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=False)
|
||||
TPS.run_tests()
|
||||
def run(self):
|
||||
# run the tests in normal mode ...
|
||||
TPS = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=self.builddata['buildurl'],
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=False)
|
||||
TPS.run_tests()
|
||||
|
||||
# Get the binary used by this TPS instance, and use it in subsequent
|
||||
# ones, so it doesn't have to be re-downloaded each time.
|
||||
binary = TPS.firefoxRunner.binary
|
||||
# Get the binary used by this TPS instance, and use it in subsequent
|
||||
# ones, so it doesn't have to be re-downloaded each time.
|
||||
binary = TPS.firefoxRunner.binary
|
||||
|
||||
# ... and then again in mobile mode
|
||||
TPS_mobile = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=True)
|
||||
TPS_mobile.run_tests()
|
||||
# ... and then again in mobile mode
|
||||
TPS_mobile = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=self.config,
|
||||
rlock=self.rlock,
|
||||
mobile=True)
|
||||
TPS_mobile.run_tests()
|
||||
|
||||
# ... and again via the staging server, if credentials are present
|
||||
stageaccount = self.config.get('stageaccount')
|
||||
if stageaccount:
|
||||
username = stageaccount.get('username')
|
||||
password = stageaccount.get('password')
|
||||
passphrase = stageaccount.get('passphrase')
|
||||
if username and password and passphrase:
|
||||
stageconfig = self.config.copy()
|
||||
stageconfig['account'] = stageaccount.copy()
|
||||
TPS_stage = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=stageconfig,
|
||||
rlock=self.rlock,
|
||||
mobile=False)#, autolog=self.autolog)
|
||||
TPS_stage.run_tests()
|
||||
# ... and again via the staging server, if credentials are present
|
||||
stageaccount = self.config.get('stageaccount')
|
||||
if stageaccount:
|
||||
username = stageaccount.get('username')
|
||||
password = stageaccount.get('password')
|
||||
passphrase = stageaccount.get('passphrase')
|
||||
if username and password and passphrase:
|
||||
stageconfig = self.config.copy()
|
||||
stageconfig['account'] = stageaccount.copy()
|
||||
TPS_stage = TPSTestRunner(self.extensionDir,
|
||||
testfile=self.testfile,
|
||||
logfile=self.logfile,
|
||||
binary=binary,
|
||||
config=stageconfig,
|
||||
rlock=self.rlock,
|
||||
mobile=False)#, autolog=self.autolog)
|
||||
TPS_stage.run_tests()
|
||||
|
@ -88,6 +88,7 @@ skip-if = os == "android"
|
||||
[include:services/common/tests/unit/xpcshell.ini]
|
||||
[include:services/crypto/tests/unit/xpcshell.ini]
|
||||
[include:services/crypto/components/tests/unit/xpcshell.ini]
|
||||
[include:services/datareporting/tests/xpcshell/xpcshell.ini]
|
||||
[include:services/healthreport/tests/xpcshell/xpcshell.ini]
|
||||
[include:services/metrics/tests/xpcshell/xpcshell.ini]
|
||||
[include:services/sync/tests/unit/xpcshell.ini]
|
||||
|
Loading…
Reference in New Issue
Block a user