зеркало из https://github.com/mozilla/gecko-dev.git
Bug 922694 - Part 4: grab Accept-Locale pref in FHR. r=mcomella
This commit is contained in:
Родитель
c146796ff8
Коммит
c9121d303f
|
@ -117,6 +117,7 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -1291,7 +1292,16 @@ abstract public class GeckoApp
|
|||
final String profilePath = getProfile().getDir().getAbsolutePath();
|
||||
final EventDispatcher dispatcher = GeckoAppShell.getEventDispatcher();
|
||||
Log.i(LOGTAG, "Creating BrowserHealthRecorder.");
|
||||
mHealthRecorder = new BrowserHealthRecorder(GeckoApp.this, profilePath, dispatcher,
|
||||
final String osLocale = Locale.getDefault().toString();
|
||||
Log.d(LOGTAG, "Locale is " + osLocale);
|
||||
|
||||
// Replace the duplicate `osLocale` argument when we support switchable
|
||||
// application locales.
|
||||
mHealthRecorder = new BrowserHealthRecorder(GeckoApp.this,
|
||||
profilePath,
|
||||
dispatcher,
|
||||
osLocale,
|
||||
osLocale, // Placeholder.
|
||||
previousSession);
|
||||
}
|
||||
});
|
||||
|
@ -1555,8 +1565,15 @@ abstract public class GeckoApp
|
|||
GeckoPreferences.broadcastHealthReportUploadPref(context);
|
||||
|
||||
/*
|
||||
XXXX see bug 635342
|
||||
We want to disable this code if possible. It is about 145ms in runtime
|
||||
XXXX see Bug 635342.
|
||||
We want to disable this code if possible. It is about 145ms in runtime.
|
||||
|
||||
If this code ever becomes live again, you'll need to chain the
|
||||
new locale into BrowserHealthRecorder correctly. See
|
||||
GeckoAppShell.setSelectedLocale.
|
||||
We pass the OS locale into the BHR constructor: we need to grab
|
||||
that *before* we modify the current locale!
|
||||
|
||||
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
||||
String localeCode = settings.getString(getPackageName() + ".locale", "");
|
||||
if (localeCode != null && localeCode.length() > 0)
|
||||
|
|
|
@ -1525,6 +1525,12 @@ public class GeckoAppShell
|
|||
Gecko resets the locale to en-US by calling this function with an empty string.
|
||||
This affects GeckoPreferences activity in multi-locale builds.
|
||||
|
||||
N.B., if this code ever becomes live again, you need to hook it up to locale
|
||||
recording in BrowserHealthRecorder: we track the current app and OS locales
|
||||
as part of the recorded environment.
|
||||
|
||||
See similar note in GeckoApp.java for the startup path.
|
||||
|
||||
//We're not using this, not need to save it (see bug 635342)
|
||||
SharedPreferences settings =
|
||||
getContext().getPreferences(Activity.MODE_PRIVATE);
|
||||
|
|
|
@ -16,8 +16,6 @@ import org.mozilla.gecko.AppConstants;
|
|||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.PrefsHelper.PrefHandler;
|
||||
|
||||
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
|
||||
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
|
||||
|
@ -38,6 +36,7 @@ import java.io.FileOutputStream;
|
|||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -50,8 +49,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
* Keep an instance of this class around.
|
||||
*
|
||||
* Tell it when an environment attribute has changed: call {@link
|
||||
* #onBlocklistPrefChanged(boolean)} or {@link
|
||||
* #onTelemetryPrefChanged(boolean)}, followed by {@link
|
||||
* #onAppLocaleChanged(String)} followed by {@link
|
||||
* #onEnvironmentChanged()}.
|
||||
*
|
||||
* Use it to record events: {@link #recordSearch(String, String)}.
|
||||
|
@ -60,8 +58,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
*/
|
||||
public class BrowserHealthRecorder implements GeckoEventListener {
|
||||
private static final String LOG_TAG = "GeckoHealthRec";
|
||||
private static final String PREF_ACCEPT_LANG = "intl.accept_languages";
|
||||
private static final String PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
|
||||
private static final String EVENT_ADDONS_ALL = "Addons:All";
|
||||
private static final String EVENT_SNAPSHOT = "HealthReport:Snapshot";
|
||||
private static final String EVENT_ADDONS_CHANGE = "Addons:Change";
|
||||
private static final String EVENT_ADDONS_UNINSTALLING = "Addons:Uninstalling";
|
||||
private static final String EVENT_PREF_CHANGE = "Pref:Change";
|
||||
|
@ -242,8 +241,15 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
|
||||
/**
|
||||
* This constructor does IO. Run it on a background thread.
|
||||
*
|
||||
* appLocale can be null, which indicates that it will be provided later.
|
||||
*/
|
||||
public BrowserHealthRecorder(final Context context, final String profilePath, final EventDispatcher dispatcher, SessionInformation previousSession) {
|
||||
public BrowserHealthRecorder(final Context context,
|
||||
final String profilePath,
|
||||
final EventDispatcher dispatcher,
|
||||
final String osLocale,
|
||||
final String appLocale,
|
||||
SessionInformation previousSession) {
|
||||
Log.d(LOG_TAG, "Initializing. Dispatcher is " + dispatcher);
|
||||
this.dispatcher = dispatcher;
|
||||
this.previousSession = previousSession;
|
||||
|
@ -263,9 +269,12 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
this.client = null;
|
||||
}
|
||||
|
||||
// Note that the PIC is not necessarily fully initialized at this point:
|
||||
// we haven't set the app locale. This must be done before an environment
|
||||
// is recorded.
|
||||
this.profileCache = new ProfileInformationCache(profilePath);
|
||||
try {
|
||||
this.initialize(context, profilePath);
|
||||
this.initialize(context, profilePath, osLocale, appLocale);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Exception initializing.", e);
|
||||
}
|
||||
|
@ -299,7 +308,7 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
}
|
||||
|
||||
private void unregisterEventListeners() {
|
||||
this.dispatcher.unregisterEventListener(EVENT_ADDONS_ALL, this);
|
||||
this.dispatcher.unregisterEventListener(EVENT_SNAPSHOT, this);
|
||||
this.dispatcher.unregisterEventListener(EVENT_ADDONS_CHANGE, this);
|
||||
this.dispatcher.unregisterEventListener(EVENT_ADDONS_UNINSTALLING, this);
|
||||
this.dispatcher.unregisterEventListener(EVENT_PREF_CHANGE, this);
|
||||
|
@ -307,14 +316,9 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
this.dispatcher.unregisterEventListener(EVENT_SEARCH, this);
|
||||
}
|
||||
|
||||
public void onBlocklistPrefChanged(boolean to) {
|
||||
public void onAppLocaleChanged(String to) {
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setBlocklistEnabled(to);
|
||||
}
|
||||
|
||||
public void onTelemetryPrefChanged(boolean to) {
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setTelemetryEnabled(to);
|
||||
this.profileCache.setAppLocale(to);
|
||||
}
|
||||
|
||||
public void onAddonChanged(String id, JSONObject json) {
|
||||
|
@ -340,8 +344,7 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
* environment, such that a new environment should be computed and prepared
|
||||
* for use in future events.
|
||||
*
|
||||
* Invoke this method after calls that mutate the environment, such as
|
||||
* {@link #onBlocklistPrefChanged(boolean)}.
|
||||
* Invoke this method after calls that mutate the environment.
|
||||
*
|
||||
* If this change resulted in a transition between two environments, {@link
|
||||
* #onEnvironmentTransition(int, int)} will be invoked on the background
|
||||
|
@ -491,14 +494,36 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
return time;
|
||||
}
|
||||
|
||||
private void handlePrefValue(final String pref, final boolean value) {
|
||||
Log.d(LOG_TAG, "Incorporating environment: " + pref + " = " + value);
|
||||
if (AppConstants.TELEMETRY_PREF_NAME.equals(pref)) {
|
||||
profileCache.setTelemetryEnabled(value);
|
||||
private void onPrefMessage(final String pref, final JSONObject message) {
|
||||
Log.d(LOG_TAG, "Incorporating environment: " + pref);
|
||||
if (PREF_ACCEPT_LANG.equals(pref)) {
|
||||
// We only record whether this is user-set.
|
||||
try {
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setAcceptLangUserSet(message.getBoolean("isUserSet"));
|
||||
} catch (JSONException ex) {
|
||||
Log.w(LOG_TAG, "Unexpected JSONException fetching isUserSet for " + pref);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (PREF_BLOCKLIST_ENABLED.equals(pref)) {
|
||||
profileCache.setBlocklistEnabled(value);
|
||||
|
||||
// (We only handle boolean prefs right now.)
|
||||
try {
|
||||
boolean value = message.getBoolean("value");
|
||||
|
||||
if (AppConstants.TELEMETRY_PREF_NAME.equals(pref)) {
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setTelemetryEnabled(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PREF_BLOCKLIST_ENABLED.equals(pref)) {
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setBlocklistEnabled(value);
|
||||
return;
|
||||
}
|
||||
} catch (JSONException ex) {
|
||||
Log.w(LOG_TAG, "Unexpected JSONException fetching boolean value for " + pref);
|
||||
return;
|
||||
}
|
||||
Log.w(LOG_TAG, "Unexpected pref: " + pref);
|
||||
|
@ -571,7 +596,9 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
* Add provider-specific initialization in this method.
|
||||
*/
|
||||
private synchronized void initialize(final Context context,
|
||||
final String profilePath)
|
||||
final String profilePath,
|
||||
final String osLocale,
|
||||
final String appLocale)
|
||||
throws java.io.IOException {
|
||||
|
||||
Log.d(LOG_TAG, "Initializing profile cache.");
|
||||
|
@ -579,6 +606,9 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
|
||||
// If we can restore state from last time, great.
|
||||
if (this.profileCache.restoreUnlessInitialized()) {
|
||||
this.profileCache.updateLocales(osLocale, appLocale);
|
||||
this.profileCache.completeInitialization();
|
||||
|
||||
Log.d(LOG_TAG, "Successfully restored state. Initializing storage.");
|
||||
initializeStorage();
|
||||
return;
|
||||
|
@ -587,31 +617,12 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
// Otherwise, let's initialize it from scratch.
|
||||
this.profileCache.beginInitialization();
|
||||
this.profileCache.setProfileCreationTime(getAndPersistProfileInitTime(context, profilePath));
|
||||
this.profileCache.setOSLocale(osLocale);
|
||||
this.profileCache.setAppLocale(appLocale);
|
||||
|
||||
final BrowserHealthRecorder self = this;
|
||||
|
||||
PrefHandler handler = new PrefsHelper.PrefHandlerBase() {
|
||||
@Override
|
||||
public void prefValue(String pref, boolean value) {
|
||||
handlePrefValue(pref, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
Log.d(LOG_TAG, "Requesting all add-ons from Gecko.");
|
||||
dispatcher.registerEventListener(EVENT_ADDONS_ALL, self);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Addons:FetchAll", null));
|
||||
// Wait for the broadcast event which completes our initialization.
|
||||
}
|
||||
};
|
||||
|
||||
// Oh, singletons.
|
||||
PrefsHelper.getPrefs(new String[] {
|
||||
AppConstants.TELEMETRY_PREF_NAME,
|
||||
PREF_BLOCKLIST_ENABLED
|
||||
},
|
||||
handler);
|
||||
Log.d(LOG_TAG, "Requested prefs.");
|
||||
Log.d(LOG_TAG, "Requesting all add-ons and FHR prefs from Gecko.");
|
||||
dispatcher.registerEventListener(EVENT_SNAPSHOT, this);
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("HealthReport:RequestSnapshot", null));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -638,12 +649,22 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
if (EVENT_ADDONS_ALL.equals(event)) {
|
||||
Log.d(LOG_TAG, "Got all add-ons.");
|
||||
if (EVENT_SNAPSHOT.equals(event)) {
|
||||
Log.d(LOG_TAG, "Got all add-ons and prefs.");
|
||||
try {
|
||||
JSONObject addons = message.getJSONObject("json");
|
||||
JSONObject json = message.getJSONObject("json");
|
||||
JSONObject addons = json.getJSONObject("addons");
|
||||
Log.i(LOG_TAG, "Persisting " + addons.length() + " add-ons.");
|
||||
profileCache.setJSONForAddons(addons);
|
||||
|
||||
JSONObject prefs = json.getJSONObject("prefs");
|
||||
Log.i(LOG_TAG, "Persisting prefs.");
|
||||
Iterator<?> keys = prefs.keys();
|
||||
while (keys.hasNext()) {
|
||||
String pref = (String) keys.next();
|
||||
this.onPrefMessage(pref, prefs.getJSONObject(pref));
|
||||
}
|
||||
|
||||
profileCache.completeInitialization();
|
||||
} catch (java.io.IOException e) {
|
||||
Log.e(LOG_TAG, "Error completing profile cache initialization.", e);
|
||||
|
@ -675,7 +696,7 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
if (EVENT_PREF_CHANGE.equals(event)) {
|
||||
final String pref = message.getString("pref");
|
||||
Log.d(LOG_TAG, "Pref changed: " + pref);
|
||||
handlePrefValue(pref, message.getBoolean("value"));
|
||||
this.onPrefMessage(pref, message);
|
||||
this.onEnvironmentChanged();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5311,7 +5311,10 @@ var FormAssistant = {
|
|||
* -- and reflect them back to Java.
|
||||
*/
|
||||
let HealthReportStatusListener = {
|
||||
TELEMETRY_PREF:
|
||||
PREF_ACCEPT_LANG: "intl.accept_languages",
|
||||
PREF_BLOCKLIST_ENABLED: "extensions.blocklist.enabled",
|
||||
|
||||
PREF_TELEMETRY_ENABLED:
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
// Telemetry pref differs based on build.
|
||||
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
|
||||
|
@ -5330,18 +5333,21 @@ let HealthReportStatusListener = {
|
|||
console.log("Failed to initialize add-on status listener. FHR cannot report add-on state. " + ex);
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, "Addons:FetchAll", false);
|
||||
Services.prefs.addObserver("extensions.blocklist.enabled", this, false);
|
||||
if (this.TELEMETRY_PREF) {
|
||||
Services.prefs.addObserver(this.TELEMETRY_PREF, this, false);
|
||||
console.log("Adding HealthReport:RequestSnapshot observer.");
|
||||
Services.obs.addObserver(this, "HealthReport:RequestSnapshot", false);
|
||||
Services.prefs.addObserver(this.PREF_ACCEPT_LANG, this, false);
|
||||
Services.prefs.addObserver(this.PREF_BLOCKLIST_ENABLED, this, false);
|
||||
if (this.PREF_TELEMETRY_ENABLED) {
|
||||
Services.prefs.addObserver(this.PREF_TELEMETRY_ENABLED, this, false);
|
||||
}
|
||||
},
|
||||
|
||||
uninit: function () {
|
||||
Services.obs.removeObserver(this, "Addons:FetchAll");
|
||||
Services.prefs.removeObserver("extensions.blocklist.enabled", this);
|
||||
if (this.TELEMETRY_PREF) {
|
||||
Services.prefs.removeObserver(this.TELEMETRY_PREF, this);
|
||||
Services.obs.removeObserver(this, "HealthReport:RequestSnapshot");
|
||||
Services.prefs.removeObserver(this.PREF_ACCEPT_LANG, this);
|
||||
Services.prefs.removeObserver(this.PREF_BLOCKLIST_ENABLED, this);
|
||||
if (this.PREF_TELEMETRY_ENABLED) {
|
||||
Services.prefs.removeObserver(this.PREF_TELEMETRY_ENABLED, this);
|
||||
}
|
||||
|
||||
AddonManager.removeAddonListener(this);
|
||||
|
@ -5349,11 +5355,30 @@ let HealthReportStatusListener = {
|
|||
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "Addons:FetchAll":
|
||||
HealthReportStatusListener.sendAllAddonsToJava();
|
||||
case "HealthReport:RequestSnapshot":
|
||||
HealthReportStatusListener.sendSnapshotToJava();
|
||||
break;
|
||||
case "nsPref:changed":
|
||||
sendMessageToJava({ type: "Pref:Change", pref: aData, value: Services.prefs.getBoolPref(aData) });
|
||||
let response = {
|
||||
type: "Pref:Change",
|
||||
pref: aData,
|
||||
isUserSet: Services.prefs.prefHasUserValue(aData),
|
||||
};
|
||||
|
||||
switch (aData) {
|
||||
case this.PREF_ACCEPT_LANG:
|
||||
response.value = Services.prefs.getCharPref(aData);
|
||||
break;
|
||||
case this.PREF_TELEMETRY_ENABLED:
|
||||
case this.PREF_BLOCKLIST_ENABLED:
|
||||
response.value = Services.prefs.getBoolPref(aData);
|
||||
break;
|
||||
default:
|
||||
console.log("Unexpected pref in HealthReportStatusListener: " + aData);
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessageToJava(response);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -5435,9 +5460,9 @@ let HealthReportStatusListener = {
|
|||
this.notifyJava(aAddon);
|
||||
},
|
||||
|
||||
sendAllAddonsToJava: function () {
|
||||
sendSnapshotToJava: function () {
|
||||
AddonManager.getAllAddons(function (aAddons) {
|
||||
let json = {};
|
||||
let jsonA = {};
|
||||
if (aAddons) {
|
||||
for (let i = 0; i < aAddons.length; ++i) {
|
||||
let addon = aAddons[i];
|
||||
|
@ -5446,14 +5471,43 @@ let HealthReportStatusListener = {
|
|||
if (HealthReportStatusListener._shouldIgnore(addon)) {
|
||||
addonJSON.ignore = true;
|
||||
}
|
||||
json[addon.id] = addonJSON;
|
||||
jsonA[addon.id] = addonJSON;
|
||||
} catch (e) {
|
||||
// Just skip this add-on.
|
||||
}
|
||||
}
|
||||
}
|
||||
sendMessageToJava({ type: "Addons:All", json: json });
|
||||
});
|
||||
|
||||
// Now add prefs.
|
||||
let jsonP = {};
|
||||
for (let pref of [this.PREF_BLOCKLIST_ENABLED, this.PREF_TELEMETRY_ENABLED]) {
|
||||
if (!pref) {
|
||||
// This will be the case for PREF_TELEMETRY_ENABLED in developer builds.
|
||||
continue;
|
||||
}
|
||||
jsonP[pref] = {
|
||||
pref: pref,
|
||||
value: Services.prefs.getBoolPref(pref),
|
||||
isUserSet: Services.prefs.prefHasUserValue(pref),
|
||||
};
|
||||
}
|
||||
for (let pref of [this.PREF_ACCEPT_LANG]) {
|
||||
jsonP[pref] = {
|
||||
pref: pref,
|
||||
value: Services.prefs.getCharPref(pref),
|
||||
isUserSet: Services.prefs.prefHasUserValue(pref),
|
||||
};
|
||||
}
|
||||
|
||||
console.log("Sending snapshot message.");
|
||||
sendMessageToJava({
|
||||
type: "HealthReport:Snapshot",
|
||||
json: {
|
||||
addons: jsonA,
|
||||
prefs: jsonP,
|
||||
},
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче