Skip to content

Commit

Permalink
Bug 1653136 - add supported for user-abandoned or server-ended studie…
Browse files Browse the repository at this point in the history
…s. r=sfoster,fluent-reviewers,flod, a=jcristau

Differential Revision: https://phabricator.services.mozilla.com/D86282
  • Loading branch information
rhelmer committed Aug 7, 2020
1 parent 162068f commit 9f9ad33
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 17 deletions.
1 change: 1 addition & 0 deletions browser/components/pioneer/content/pioneer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ pioneer-enrollment-button = Enroll
pioneer-unenrollment-button = Leave
pioneer-available-studies = Available Studies
pioneer-end-study = End Study
pioneer-ended-study = Study Ended
74 changes: 69 additions & 5 deletions browser/components/pioneer/content/pioneer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,19 @@ XPCOMUtils.defineLazyModuleGetters(this, {
const PREF_PIONEER_ID = "toolkit.telemetry.pioneerId";
const PREF_PIONEER_NEW_STUDIES_AVAILABLE =
"toolkit.telemetry.pioneer-new-studies-available";
const PREF_PIONEER_COMPLETED_STUDIES =
"toolkit.telemetry.pioneer-completed-studies";

/**
* This is the Remote Settings key that we use to get the list of available studies.
*/
const STUDY_ADDON_COLLECTION_KEY = "pioneer-study-addons-v1";

const STUDY_LEAVE_REASONS = {
USER_ABANDONED: "user-abandoned",
STUDY_ENDED: "study-ended",
};

const PREF_TEST_CACHED_ADDONS = "toolkit.pioneer.testCachedAddons";
const PREF_TEST_ADDONS = "toolkit.pioneer.testAddons";

Expand Down Expand Up @@ -171,12 +178,40 @@ async function showAvailableStudies(cachedAddons) {
);
}

const completedStudies = Services.prefs.getStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
"{}"
);

if (addon) {
joinBtn.disabled = true;
await addon.uninstall();
document.l10n.setAttributes(joinBtn, "pioneer-join-study");
joinBtn.disabled = false;

// Record that the user abandoned this study, since it may not be re-join-able.
if (completedStudies) {
const studies = JSON.parse(completedStudies);
studies[studyAddonId] = STUDY_LEAVE_REASONS.USER_ABANDONED;
Services.prefs.setStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
JSON.stringify(studies)
);
}
} else {
// Check if this study is re-join-able before enrollment.
const studies = JSON.parse(completedStudies);
if (studyAddonId in studies) {
if (
"canRejoin" in cachedAddons[studyAddonId] &&
cachedAddons[studyAddonId].canRejoin === false
) {
console.error(
`Cannot rejoin ended study ${studyAddonId}, reason: ${studies[studyAddonId]}`
);
return;
}
}
joinBtn.disabled = true;
await install.install();
document.l10n.setAttributes(joinBtn, "pioneer-leave-study");
Expand Down Expand Up @@ -214,13 +249,24 @@ async function updateStudy(studyAddonId) {
const pioneerId = Services.prefs.getStringPref(PREF_PIONEER_ID, null);

if (pioneerId) {
study.style.opacity = 1;
joinBtn.disabled = false;
const completedStudies = Services.prefs.getStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
"{}"
);

if (addon) {
document.l10n.setAttributes(joinBtn, "pioneer-leave-study");
const studies = JSON.parse(completedStudies);
if (studyAddonId in studies) {
joinBtn.disabled = true;
document.l10n.setAttributes(joinBtn, "pioneer-ended-study");
} else {
document.l10n.setAttributes(joinBtn, "pioneer-join-study");
study.style.opacity = 1;
joinBtn.disabled = false;

if (addon) {
document.l10n.setAttributes(joinBtn, "pioneer-leave-study");
} else {
document.l10n.setAttributes(joinBtn, "pioneer-join-study");
}
}
} else {
document.l10n.setAttributes(joinBtn, "pioneer-join-study");
Expand All @@ -247,6 +293,7 @@ async function setup(cachedAddons) {

if (pioneerId) {
Services.prefs.clearUserPref(PREF_PIONEER_ID);
Services.prefs.clearUserPref(PREF_PIONEER_COMPLETED_STUDIES);
for (const cachedAddon of cachedAddons) {
const addon = await AddonManager.getAddonByID(cachedAddon.addon_id);
if (addon) {
Expand Down Expand Up @@ -345,6 +392,23 @@ document.addEventListener("DOMContentLoaded", async domEvent => {
cachedAddons = await RemoteSettings(STUDY_ADDON_COLLECTION_KEY).get();
}

for (const cachedAddon of cachedAddons) {
// Record any studies that have been marked as concluded on the server.
if ("studyEnded" in cachedAddon && cachedAddon.studyEnded === true) {
const completedStudies = Services.prefs.getStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
"{}"
);
const studies = JSON.parse(completedStudies);
studies[cachedAddon.addon_id] = STUDY_LEAVE_REASONS.STUDY_ENDED;

Services.prefs.setStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
JSON.stringify(studies)
);
}
}

await setup(cachedAddons);
await showAvailableStudies(cachedAddons);
});
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
}
}
}
},
"isDefault": {
"type": "boolean"
},
"studyEnded": {
"type": "boolean"
}
},
"required": [
Expand All @@ -91,6 +97,8 @@
"studyType",
"moreInfo",
"dataCollectionDetails",
"authors"
"authors",
"isDefault",
"studyEnded"
]
}
38 changes: 27 additions & 11 deletions browser/components/pioneer/test/browser/browser_pioneer_ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* 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";

ChromeUtils.defineModuleGetter(
Expand All @@ -17,6 +13,8 @@ ChromeUtils.defineModuleGetter(
const PREF_PIONEER_ID = "toolkit.telemetry.pioneerId";
const PREF_PIONEER_NEW_STUDIES_AVAILABLE =
"toolkit.telemetry.pioneer-new-studies-available";
const PREF_PIONEER_COMPLETED_STUDIES =
"toolkit.telemetry.pioneer-completed-studies";

const PREF_TEST_CACHED_ADDONS = "toolkit.pioneer.testCachedAddons";
const PREF_TEST_ADDONS = "toolkit.pioneer.testAddons";
Expand Down Expand Up @@ -51,6 +49,7 @@ const CACHED_ADDONS = [
spec: "http://localhost",
},
isDefault: false,
studyEnded: true,
},
{
addon_id: "[email protected]",
Expand Down Expand Up @@ -81,6 +80,7 @@ const CACHED_ADDONS = [
spec: "http://localhost",
},
isDefault: true,
studyEnded: false,
},
{
addon_id: "study@partner",
Expand Down Expand Up @@ -111,6 +111,7 @@ const CACHED_ADDONS = [
spec: "http://localhost",
},
isDefault: false,
studyEnded: false,
},
];

Expand All @@ -134,7 +135,7 @@ add_task(async function testMockSchema() {
throw new Error("Failed to load PioneerStudyAddonsSchema");
}

const ajv = new Ajv();
const ajv = new Ajv({ allErrors: true });
const validate = ajv.compile(schema);

for (const addon of CACHED_ADDONS) {
Expand Down Expand Up @@ -229,8 +230,25 @@ add_task(async function testAboutPage() {
continue;
}

ok(!joinButton.disabled, "After enrollment, join button is enabled.");
ok(!joinButton.hidden, "After enrollment, join button is not hidden.");
const completedStudies = Services.prefs.getStringPref(
PREF_PIONEER_COMPLETED_STUDIES,
"{}"
);

const studies = JSON.parse(completedStudies);

if (cachedAddon.studyEnded || Object.keys(studies).includes(addonId)) {
ok(
joinButton.disabled,
"Join button is disabled, study has already ended."
);
continue;
}

await waitForAnimationFrame();

ok(!joinButton.disabled, "Before enrollment, join button is enabled.");

for (const testAddon of TEST_ADDONS) {
if (testAddon.id == addonId) {
Services.prefs.setStringPref(
Expand All @@ -240,6 +258,8 @@ add_task(async function testAboutPage() {
}
}

await waitForAnimationFrame();

joinButton.click();
await waitForAnimationFrame();

Expand Down Expand Up @@ -279,10 +299,6 @@ add_task(async function testAboutPage() {
joinButton.disabled,
"After unenrollment, join button is disabled."
);
ok(
!joinButton.hidden,
"After unenrollment, join button is not hidden."
);

joinButton.click();
await waitForAnimationFrame();
Expand Down

0 comments on commit 9f9ad33

Please sign in to comment.