author | Petru Lingurar <petru.lingurar@softvision.ro> |
Thu, 21 Jun 2018 09:33:20 +0300 | |
changeset 809085 | 0d03ca9c61ddecad2a84332688381aa598fa95b4 |
parent 808264 | 1e2c9151a09e43613a79daa8d4a94dc3e314020c |
push id | 113542 |
push user | plingurar@mozilla.com |
push date | Thu, 21 Jun 2018 06:34:26 +0000 |
reviewers | sebastian, jchen |
bugs | 1464990 |
milestone | 62.0a1 |
new file mode 100644 --- /dev/null +++ b/mobile/android/chrome/content/aboutExperiments.js @@ -0,0 +1,113 @@ +/* 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.import("resource://gre/modules/Services.jsm"); +ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetters(this, { + AndroidLog: "resource://gre/modules/AndroidLog.jsm", + EventDispatcher: "resource://gre/modules/Messaging.jsm", +}); + +const LOGTAG = "Experiments"; +const EXPERIMENTS_CONFIGURATION = "https://firefox.settings.services.mozilla.com/v1/buckets/fennec/collections/experiments/records"; +const Experiments = Services.wm.getMostRecentWindow("navigator:browser").Experiments; + +document.addEventListener("DOMContentLoaded", initList); + +function log(msg) { + AndroidLog.d(LOGTAG, msg); +} + +function initList() { + const list = document.getElementById("list"); + list.addEventListener("click", toggleOverride); + + Promise.all([promiseEnabledExperiments(), promiseExperimentsConfiguration()]).then(values => { + const enabledExperiments = values[0]; + const serverConfiguration = values[1]; + + serverConfiguration.data.forEach(function(experiment) { + try { + let item = document.createElement("li"); + item.textContent = experiment.name; + item.setAttribute("name", experiment.name); + item.setAttribute("isEnabled", enabledExperiments.includes(experiment.name)); + list.appendChild(item); + } catch (e) { + log(`Error while setting experiments list: ${e.error}`); + } + }); + }); +} + +function toggleOverride(experiment) { + const item = experiment.originalTarget; + const name = item.getAttribute("name"); + const isEnabled = item.getAttribute("isEnabled") === "true"; + + log(`toggleOverride: ${name}`); + + Experiments.setOverride(name, !isEnabled); + item.setAttribute("isEnabled", !isEnabled); +} + +/** + * Get the list of locally enabled experiments. + */ +function promiseEnabledExperiments() { + log("Getting the locally enabled experiments"); + + return EventDispatcher.instance.sendRequestForResult({ + type: "Experiments:GetActive" + }).then(experiments => { + log("List of locally enabled experiments ready"); + return experiments; + }); +} + +/** + * Fetch the list of experiments from server configuration. + */ +function promiseExperimentsConfiguration() { + log("Fetching server experiments"); + + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + + try { + xhr.open("GET", EXPERIMENTS_CONFIGURATION, true); + } catch (e) { + reject(`Error opening request: ${e}`); + return; + } + + xhr.onerror = function(e) { + reject(`Error making request: ${e.error}`); + }; + + xhr.onload = function(event) { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + try { + resolve(JSON.parse(xhr.responseText)); + } catch (e) { + const errorMessage = `Error while parsing request: ${e}`; + log(errorMessage); + reject(errorMessage); + } + } else { + const errorMessage = `Request to ${url} returned status ${xhr.status}`; + log(errorMessage); + reject(errorMessage); + } + } + log("Finished fetching server experiments"); + }; + + xhr.send(null); + }); +}
new file mode 100644 --- /dev/null +++ b/mobile/android/chrome/content/aboutExperiments.xhtml @@ -0,0 +1,18 @@ +<?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/. --> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>Switchboard Experiments</title> + <meta name="viewport" content="width=device-width; user-scalable=0" /> + <link rel="stylesheet" href="chrome://browser/skin/aboutBase.css" type="text/css"/> + <link rel="stylesheet" href="chrome://browser/skin/aboutExperiments.css" type="text/css"/> + <script type="application/javascript" src="chrome://browser/content/aboutExperiments.js"></script> + </head> + + <body> + <ul id="list"/> + </body> +</html>
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -5622,17 +5622,17 @@ var IdentityHandler = { if (aState & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) { return this.IDENTITY_MODE_VERIFIED; } if (aState & Ci.nsIWebProgressListener.STATE_IS_SECURE) { return this.IDENTITY_MODE_IDENTIFIED; } - let whitelist = /^about:(about|accounts|addons|buildconfig|cache|config|crashes|devices|downloads|fennec|firefox|feedback|home|license|logins|logo|memory|mozilla|networking|privatebrowsing|rights|serviceworkers|support|telemetry|webrtc)($|\?)/i; + let whitelist = /^about:(about|accounts|addons|buildconfig|cache|config|crashes|devices|downloads|experiments|fennec|firefox|feedback|home|license|logins|logo|memory|mozilla|networking|privatebrowsing|rights|serviceworkers|support|telemetry|webrtc)($|\?)/i; if (uri.schemeIs("about") && whitelist.test(uri.spec)) { return this.IDENTITY_MODE_CHROMEUI; } return this.IDENTITY_MODE_UNKNOWN; }, getMixedDisplayMode: function getMixedDisplayMode(aState) {
--- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -40,16 +40,18 @@ chrome.jar: content/PermissionsHelper.js (content/PermissionsHelper.js) content/FeedHandler.js (content/FeedHandler.js) content/Feedback.js (content/Feedback.js) content/Linkify.js (content/Linkify.js) content/CastingApps.js (content/CastingApps.js) content/RemoteDebugger.js (content/RemoteDebugger.js) content/aboutAccounts.xhtml (content/aboutAccounts.xhtml) content/aboutAccounts.js (content/aboutAccounts.js) + content/aboutExperiments.xhtml (content/aboutExperiments.xhtml) + content/aboutExperiments.js (content/aboutExperiments.js) content/aboutLogins.xhtml (content/aboutLogins.xhtml) content/aboutLogins.js (content/aboutLogins.js) #ifndef RELEASE_OR_BETA content/WebcompatReporter.js (content/WebcompatReporter.js) #endif content/ExtensionPermissions.js (content/ExtensionPermissions.js) % content branding %content/branding/
--- a/mobile/android/components/AboutRedirector.js +++ b/mobile/android/components/AboutRedirector.js @@ -62,16 +62,21 @@ var modules = { logins: { uri: "chrome://browser/content/aboutLogins.xhtml", privileged: true }, accounts: { uri: "chrome://browser/content/aboutAccounts.xhtml", privileged: true }, + experiments: { + uri: "chrome://browser/content/aboutExperiments.xhtml", + privileged: true, + hide: true + }, }; function AboutRedirector() {} AboutRedirector.prototype = { QueryInterface: ChromeUtils.generateQI([Ci.nsIAboutModule]), classID: Components.ID("{322ba47e-7047-4f71-aebf-cb7d69325cd9}"), _getModuleInfo: function(aURI) {
--- a/mobile/android/components/MobileComponents.manifest +++ b/mobile/android/components/MobileComponents.manifest @@ -9,16 +9,17 @@ contract @mozilla.org/network/protocol/a contract @mozilla.org/network/protocol/about;1?what=home {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=downloads {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=reader {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=feedback {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=privatebrowsing {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=blocked {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=accounts {322ba47e-7047-4f71-aebf-cb7d69325cd9} contract @mozilla.org/network/protocol/about;1?what=logins {322ba47e-7047-4f71-aebf-cb7d69325cd9} +contract @mozilla.org/network/protocol/about;1?what=experiments {322ba47e-7047-4f71-aebf-cb7d69325cd9} # DirectoryProvider.js component {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} DirectoryProvider.js contract @mozilla.org/browser/directory-provider;1 {ef0f7a87-c1ee-45a8-8d67-26f586e46a4b} category xpcom-directory-providers browser-directory-provider @mozilla.org/browser/directory-provider;1 # stylesheets category agent-style-sheets browser-content-stylesheet chrome://geckoview/skin/content.css
new file mode 100644 --- /dev/null +++ b/mobile/android/themes/core/aboutExperiments.css @@ -0,0 +1,19 @@ +/* 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/. */ + +ul { + list-style: none; + margin: 0; + padding: 0; +} +li { + padding: 25px; + margin-bottom: 5px; +} +li[isEnabled="true"] { + background-color: #c5e1a5; +} +li[isEnabled="false"] { + background-color: #ef9a9a; +} \ No newline at end of file
--- a/mobile/android/themes/core/jar.mn +++ b/mobile/android/themes/core/jar.mn @@ -7,16 +7,17 @@ chrome.jar: % skin browser classic/1.0 %skin/ skin/aboutPage.css (aboutPage.css) skin/about.css (about.css) skin/aboutAccounts.css (aboutAccounts.css) skin/aboutAddons.css (aboutAddons.css) skin/aboutBase.css (aboutBase.css) skin/aboutDownloads.css (aboutDownloads.css) + skin/aboutExperiments.css (aboutExperiments.css) skin/aboutMemory.css (aboutMemory.css) skin/aboutPrivateBrowsing.css (aboutPrivateBrowsing.css) skin/aboutReader.css (aboutReader.css) skin/aboutSupport.css (aboutSupport.css) skin/config.css (config.css) skin/defines.css (defines.css) skin/netError.css (netError.css) skin/spinner.css (spinner.css)