зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to m-i.
This commit is contained in:
Коммит
bf96eadef1
|
@ -128,7 +128,7 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||
if not os.path.exists(state_env_dir):
|
||||
print('Creating global state directory from environment variable: %s'
|
||||
% state_env_dir)
|
||||
os.makedirs(state_env_dir, mode=0777)
|
||||
os.makedirs(state_env_dir, mode=0o770)
|
||||
print('Please re-run mach.')
|
||||
sys.exit(1)
|
||||
else:
|
||||
|
|
10
configure.in
10
configure.in
|
@ -7844,7 +7844,15 @@ else
|
|||
fi
|
||||
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "android"; then
|
||||
dnl On Android, static resources live in the assets/ folder of the APK.
|
||||
dnl Fennec's static resources live in the assets/ folder of the
|
||||
dnl APK. Adding a path to the name here works because we only
|
||||
dnl have one omnijar file in the final package (which is not the
|
||||
dnl case on desktop), and necessitates some contortions during
|
||||
dnl packaging so that the resources in the omnijar are considered
|
||||
dnl as rooted at / and not as rooted at assets/ (which again is
|
||||
dnl not the case on desktop: there are omnijars rooted at webrtc/,
|
||||
dnl etc). packager.mk handles changing the rooting of the single
|
||||
dnl omnijar.
|
||||
OMNIJAR_NAME=assets/omni.ja
|
||||
else
|
||||
OMNIJAR_NAME=omni.ja
|
||||
|
|
|
@ -556,9 +556,13 @@ abstract public class GeckoApp
|
|||
geckoConnected();
|
||||
|
||||
// This method is already running on the background thread, so we
|
||||
// know that mHealthRecorder will exist. This method is cheap, so
|
||||
// don't spawn a new runnable.
|
||||
mHealthRecorder.recordGeckoStartupTime(mGeckoReadyStartupTimer.getElapsed());
|
||||
// know that mHealthRecorder will exist. That doesn't stop us being
|
||||
// paranoid.
|
||||
// This method is cheap, so don't spawn a new runnable.
|
||||
final BrowserHealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.recordGeckoStartupTime(mGeckoReadyStartupTimer.getElapsed());
|
||||
}
|
||||
} else if (event.equals("ToggleChrome:Hide")) {
|
||||
toggleChrome(false);
|
||||
} else if (event.equals("ToggleChrome:Show")) {
|
||||
|
@ -1532,7 +1536,10 @@ abstract public class GeckoApp
|
|||
ThreadUtils.getBackgroundHandler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mHealthRecorder.recordJavaStartupTime(javaDuration);
|
||||
final BrowserHealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.recordJavaStartupTime(javaDuration);
|
||||
}
|
||||
|
||||
// Sync settings need Gecko to be loaded, so
|
||||
// no hurry in starting this.
|
||||
|
@ -1879,7 +1886,6 @@ abstract public class GeckoApp
|
|||
// track the duration of the session.
|
||||
final long now = System.currentTimeMillis();
|
||||
final long realTime = android.os.SystemClock.elapsedRealtime();
|
||||
final BrowserHealthRecorder rec = mHealthRecorder;
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
|
@ -1894,8 +1900,11 @@ abstract public class GeckoApp
|
|||
currentSession.recordBegin(editor);
|
||||
editor.commit();
|
||||
|
||||
final BrowserHealthRecorder rec = mHealthRecorder;
|
||||
if (rec != null) {
|
||||
rec.setCurrentSession(currentSession);
|
||||
} else {
|
||||
Log.w(LOGTAG, "Can't record session: rec is null.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -427,7 +427,16 @@ public class HealthReportGenerator {
|
|||
|
||||
/**
|
||||
* Compute the *tree* difference set between the two objects. If the two
|
||||
* objects are identical, returns null.
|
||||
* objects are identical, returns <code>null</code>. If <code>from</code> is
|
||||
* <code>null</code>, returns <code>to</code>. If <code>to</code> is
|
||||
* <code>null</code>, behaves as if <code>to</code> were an empty object.
|
||||
*
|
||||
* (Note that this method does not check for {@link JSONObject#NULL}, because
|
||||
* by definition it can't be provided as input to this method.)
|
||||
*
|
||||
* This behavior is intended to simplify life for callers: a missing object
|
||||
* can be viewed as (and behaves as) an empty map, to a useful extent, rather
|
||||
* than throwing an exception.
|
||||
*
|
||||
* @param from
|
||||
* a JSONObject.
|
||||
|
@ -445,10 +454,14 @@ public class HealthReportGenerator {
|
|||
public static JSONObject diff(JSONObject from,
|
||||
JSONObject to,
|
||||
boolean includeNull) throws JSONException {
|
||||
if (from == null || from == JSONObject.NULL) {
|
||||
if (from == null) {
|
||||
return to;
|
||||
}
|
||||
|
||||
if (to == null) {
|
||||
return diff(from, new JSONObject(), includeNull);
|
||||
}
|
||||
|
||||
JSONObject out = new JSONObject();
|
||||
|
||||
HashSet<String> toKeys = includeNull ? new HashSet<String>(to.length())
|
||||
|
|
|
@ -777,9 +777,17 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
final int day = storage.getDay();
|
||||
final int env = this.env;
|
||||
final String key = getEngineKey(engine);
|
||||
final BrowserHealthRecorder self = this;
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final HealthReportDatabaseStorage storage = self.storage;
|
||||
if (storage == null) {
|
||||
Log.d(LOG_TAG, "No storage: not recording search. Shutting down?");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(LOG_TAG, "Recording search: " + key + ", " + location +
|
||||
" (" + day + ", " + env + ").");
|
||||
final int searchField = storage.getField(MEASUREMENT_NAME_SEARCH_COUNTS,
|
||||
|
@ -829,8 +837,12 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
*
|
||||
* "r": reason. Values are "P" (activity paused), "A" (abnormal termination)
|
||||
* "d": duration. Value in seconds.
|
||||
* "sg": Gecko startup time. Present if this is a clean launch.
|
||||
* "sj": Java startup time. Present if this is a clean launch.
|
||||
* "sg": Gecko startup time. Present if this is a clean launch. This
|
||||
* corresponds to the telemetry timer FENNEC_STARTUP_TIME_GECKOREADY.
|
||||
* "sj": Java activity init time. Present if this is a clean launch. This
|
||||
* corresponds to the telemetry timer FENNEC_STARTUP_TIME_JAVAUI,
|
||||
* and includes initialization tasks beyond initial
|
||||
* onWindowFocusChanged.
|
||||
*
|
||||
* Abnormal terminations will be missing a duration and will feature these keys:
|
||||
*
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.mozilla.gecko.GeckoEvent;
|
|||
import org.mozilla.gecko.GeckoProfile;
|
||||
|
||||
import org.mozilla.gecko.background.healthreport.EnvironmentBuilder;
|
||||
import org.mozilla.gecko.background.healthreport.HealthReportConstants;
|
||||
import org.mozilla.gecko.background.healthreport.HealthReportDatabaseStorage;
|
||||
import org.mozilla.gecko.background.healthreport.HealthReportGenerator;
|
||||
|
||||
|
@ -34,16 +35,15 @@ import org.json.JSONObject;
|
|||
public class BrowserHealthReporter implements GeckoEventListener {
|
||||
private static final String LOGTAG = "GeckoHealthRep";
|
||||
|
||||
public static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
||||
public static final long MILLISECONDS_PER_SIX_MONTHS = 180 * MILLISECONDS_PER_DAY;
|
||||
|
||||
public static final String EVENT_REQUEST = "HealthReport:Request";
|
||||
public static final String EVENT_RESPONSE = "HealthReport:Response";
|
||||
|
||||
protected final Context context;
|
||||
|
||||
public BrowserHealthReporter() {
|
||||
GeckoAppShell.registerEventListener(EVENT_REQUEST, this);
|
||||
|
||||
final Context context = GeckoAppShell.getContext();
|
||||
context = GeckoAppShell.getContext();
|
||||
if (context == null) {
|
||||
throw new IllegalStateException("Null Gecko context");
|
||||
}
|
||||
|
@ -62,14 +62,11 @@ public class BrowserHealthReporter implements GeckoEventListener {
|
|||
* @param lastPingTime timestamp when last health report was uploaded
|
||||
* (milliseconds since epoch).
|
||||
* @param profilePath path of the profile to generate report for.
|
||||
* @throws JSONException if JSON generation fails.
|
||||
* @throws IllegalStateException if the environment does not allow to generate a report.
|
||||
* @return non-null report.
|
||||
*/
|
||||
public JSONObject generateReport(long since, long lastPingTime, String profilePath) throws JSONException {
|
||||
final Context context = GeckoAppShell.getContext();
|
||||
if (context == null) {
|
||||
Log.e(LOGTAG, "Null Gecko context; returning null report.", new RuntimeException());
|
||||
return null;
|
||||
}
|
||||
|
||||
// We abuse the life-cycle of an Android ContentProvider slightly by holding
|
||||
// onto a ContentProviderClient while we generate a payload. This keeps
|
||||
// our database storage alive, while also allowing us to share a database
|
||||
|
@ -86,29 +83,50 @@ public class BrowserHealthReporter implements GeckoEventListener {
|
|||
// to close it.
|
||||
HealthReportDatabaseStorage storage = EnvironmentBuilder.getStorage(client, profilePath);
|
||||
if (storage == null) {
|
||||
Log.e(LOGTAG, "No storage in health reporter; returning null report.", new RuntimeException());
|
||||
return null;
|
||||
throw new IllegalStateException("No storage in Health Reporter.");
|
||||
}
|
||||
|
||||
HealthReportGenerator generator = new HealthReportGenerator(storage);
|
||||
return generator.generateDocument(since, lastPingTime, profilePath);
|
||||
JSONObject report = generator.generateDocument(since, lastPingTime, profilePath);
|
||||
if (report == null) {
|
||||
throw new IllegalStateException("Not enough profile information to generate report.");
|
||||
}
|
||||
return report;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last time a health report was successfully uploaded.
|
||||
*
|
||||
* This is read from shared preferences, so call it from a background
|
||||
* thread. Bug 882182 tracks making this work with multiple profiles.
|
||||
*
|
||||
* @return milliseconds since the epoch, or 0 if never uploaded.
|
||||
*/
|
||||
protected long getLastUploadLocalTime() {
|
||||
return context
|
||||
.getSharedPreferences(HealthReportConstants.PREFS_BRANCH, 0)
|
||||
.getLong(HealthReportConstants.PREF_LAST_UPLOAD_LOCAL_TIME, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new Health Report for the current Gecko profile.
|
||||
*
|
||||
* This method performs IO, so call it from a background thread.
|
||||
*
|
||||
* @throws JSONException if JSON generation fails.
|
||||
* @throws IllegalStateException if the environment does not allow to generate a report.
|
||||
* @return non-null Health Report.
|
||||
*/
|
||||
public JSONObject generateReport() throws JSONException {
|
||||
GeckoProfile profile = GeckoAppShell.getGeckoInterface().getProfile();
|
||||
String profilePath = profile.getDir().getAbsolutePath();
|
||||
|
||||
long since = System.currentTimeMillis() - MILLISECONDS_PER_SIX_MONTHS;
|
||||
// TODO: read this from per-profile SharedPreference owned by background uploader.
|
||||
long lastPingTime = since;
|
||||
long since = System.currentTimeMillis() - HealthReportConstants.MILLISECONDS_PER_SIX_MONTHS;
|
||||
long lastPingTime = Math.max(getLastUploadLocalTime(), HealthReportConstants.EARLIEST_LAST_PING);
|
||||
|
||||
return generateReport(since, lastPingTime, profilePath);
|
||||
}
|
||||
|
||||
|
@ -118,11 +136,12 @@ public class BrowserHealthReporter implements GeckoEventListener {
|
|||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
JSONObject report = new JSONObject();
|
||||
JSONObject report = null;
|
||||
try {
|
||||
report = generateReport();
|
||||
report = generateReport(); // non-null if it returns.
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Generating report failed; responding with null.", e);
|
||||
Log.e(LOGTAG, "Generating report failed; responding with empty report.", e);
|
||||
report = new JSONObject();
|
||||
}
|
||||
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(EVENT_RESPONSE, report.toString()));
|
||||
|
|
|
@ -204,7 +204,6 @@ function FormTracker(name, engine) {
|
|||
Tracker.call(this, name, engine);
|
||||
Svc.Obs.add("weave:engine:start-tracking", this);
|
||||
Svc.Obs.add("weave:engine:stop-tracking", this);
|
||||
Svc.Obs.add("profile-change-teardown", this);
|
||||
}
|
||||
FormTracker.prototype = {
|
||||
__proto__: Tracker.prototype,
|
||||
|
@ -243,16 +242,17 @@ FormTracker.prototype = {
|
|||
case "satchel-storage-changed":
|
||||
if (data == "formhistory-add" || data == "formhistory-remove") {
|
||||
let guid = subject.QueryInterface(Ci.nsISupportsString).toString();
|
||||
this.addChangedID(guid);
|
||||
this.score += SCORE_INCREMENT_MEDIUM;
|
||||
this.trackEntry(guid);
|
||||
}
|
||||
break;
|
||||
case "profile-change-teardown":
|
||||
FormWrapper._finalize();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
trackEntry: function (guid) {
|
||||
this.addChangedID(guid);
|
||||
this.score += SCORE_INCREMENT_MEDIUM;
|
||||
},
|
||||
|
||||
notify: function (formElement, aWindow, actionURI) {
|
||||
if (this.ignoreAll) {
|
||||
return;
|
||||
|
@ -320,7 +320,10 @@ FormTracker.prototype = {
|
|||
// Get the GUID on a delay so that it can be added to the DB first...
|
||||
Utils.nextTick(function() {
|
||||
this._log.trace("Logging form element: " + [name, el.value]);
|
||||
this.trackEntry(name, el.value);
|
||||
let guid = FormWrapper.getGUID(name, el.value);
|
||||
if (guid) {
|
||||
this.trackEntry(guid);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,6 +357,19 @@ ifdef MOZ_ENABLE_SZIP
|
|||
SZIP_LIBRARIES := $(ASSET_SO_LIBRARIES)
|
||||
endif
|
||||
|
||||
# Fennec's OMNIJAR_NAME can include a directory; for example, it might
|
||||
# be "assets/omni.ja". This path specifies where the omni.ja file
|
||||
# lives in the APK, but should not root the resources it contains
|
||||
# under assets/ (i.e., resources should not live at chrome://assets/).
|
||||
# packager.py writes /omni.ja in order to be consistent with the
|
||||
# layout expected by language repacks. Therefore, we move it to the
|
||||
# correct path here, in INNER_MAKE_PACKAGE. See comment about
|
||||
# OMNIJAR_NAME in configure.in.
|
||||
|
||||
# OMNIJAR_DIR is './' for "omni.ja", 'assets/' for "assets/omni.ja".
|
||||
OMNIJAR_DIR := $(dir $(OMNIJAR_NAME))
|
||||
OMNIJAR_NAME := $(notdir $(OMNIJAR_NAME))
|
||||
|
||||
PKG_SUFFIX = .apk
|
||||
INNER_MAKE_PACKAGE = \
|
||||
$(if $(ALREADY_SZIPPED),,$(foreach lib,$(SZIP_LIBRARIES),host/bin/szip $(MOZ_SZIP_FLAGS) $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/$(lib) && )) \
|
||||
|
@ -369,7 +382,9 @@ INNER_MAKE_PACKAGE = \
|
|||
rm $(_ABS_DIST)/gecko.ap_ && \
|
||||
$(ZIP) -0 $(_ABS_DIST)/gecko.ap_ $(ASSET_SO_LIBRARIES) && \
|
||||
$(ZIP) -r9D $(_ABS_DIST)/gecko.ap_ $(DIST_FILES) -x $(NON_DIST_FILES) $(SZIP_LIBRARIES) && \
|
||||
$(ZIP) -0 $(_ABS_DIST)/gecko.ap_ $(OMNIJAR_NAME)) && \
|
||||
$(if $(filter-out ./,$(OMNIJAR_DIR)), \
|
||||
mkdir -p $(OMNIJAR_DIR) && mv $(OMNIJAR_NAME) $(OMNIJAR_DIR) && ) \
|
||||
$(ZIP) -0 $(_ABS_DIST)/gecko.ap_ $(OMNIJAR_DIR)$(OMNIJAR_NAME)) && \
|
||||
rm -f $(_ABS_DIST)/gecko.apk && \
|
||||
cp $(_ABS_DIST)/gecko.ap_ $(_ABS_DIST)/gecko.apk && \
|
||||
$(ZIP) -j0 $(_ABS_DIST)/gecko.apk $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/classes.dex && \
|
||||
|
@ -378,13 +393,21 @@ INNER_MAKE_PACKAGE = \
|
|||
$(ZIPALIGN) -f -v 4 $(_ABS_DIST)/gecko.apk $(PACKAGE) && \
|
||||
$(INNER_ROBOCOP_PACKAGE)
|
||||
|
||||
# Language repacks root the resources contained in assets/omni.ja
|
||||
# under assets/, but the repacks expect them to be rooted at /.
|
||||
# Therefore, we we move the omnijar back to / so the resources are
|
||||
# under the root here, in INNER_UNMAKE_PACKAGE. See comments about
|
||||
# OMNIJAR_NAME earlier in this file and in configure.in.
|
||||
|
||||
INNER_UNMAKE_PACKAGE = \
|
||||
mkdir $(MOZ_PKG_DIR) && \
|
||||
( cd $(MOZ_PKG_DIR) && \
|
||||
$(UNZIP) $(UNPACKAGE) && \
|
||||
mv lib/$(ABI_DIR)/libmozglue.so . && \
|
||||
mv lib/$(ABI_DIR)/*plugin-container* $(MOZ_CHILD_PROCESS_NAME) && \
|
||||
rm -rf lib/$(ABI_DIR) )
|
||||
rm -rf lib/$(ABI_DIR) \
|
||||
$(if $(filter-out ./,$(OMNIJAR_DIR)), \
|
||||
&& mv $(OMNIJAR_DIR)$(OMNIJAR_NAME) $(OMNIJAR_NAME)) )
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_PKG_FORMAT),DMG)
|
||||
|
@ -584,8 +607,12 @@ endif
|
|||
|
||||
export NO_PKG_FILES USE_ELF_HACK ELF_HACK_FLAGS
|
||||
|
||||
# Override the value of OMNIJAR_NAME from config.status with the value
|
||||
# set earlier in this file.
|
||||
|
||||
stage-package: $(MOZ_PKG_MANIFEST)
|
||||
@rm -rf $(DIST)/$(PKG_PATH)$(PKG_BASENAME).tar $(DIST)/$(PKG_PATH)$(PKG_BASENAME).dmg $@ $(EXCLUDE_LIST)
|
||||
OMNIJAR_NAME=$(OMNIJAR_NAME) \
|
||||
$(PYTHON) $(MOZILLA_DIR)/toolkit/mozapps/installer/packager.py $(DEFINES) \
|
||||
--format $(MOZ_PACKAGER_FORMAT) \
|
||||
$(addprefix --removals ,$(MOZ_PKG_REMOVALS)) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче