зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central
This commit is contained in:
Коммит
b377b7d2b5
|
@ -213,7 +213,6 @@ let gFxAccounts = {
|
|||
},
|
||||
|
||||
openSignInAgainPage: function () {
|
||||
// FIXME: This should actually show the pre-filled username version of about:accounts?
|
||||
switchToTabHavingURI("about:accounts?signin=true", true);
|
||||
switchToTabHavingURI("about:accounts?action=reauth", true);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -173,6 +173,7 @@ toolbar[customizing] > .overflow-button {
|
|||
}
|
||||
|
||||
%ifdef CAN_DRAW_IN_TITLEBAR
|
||||
#main-window:not([chromemargin]) > #titlebar,
|
||||
#main-window[inFullscreen] > #titlebar,
|
||||
#main-window[inFullscreen] .titlebar-placeholder,
|
||||
#main-window:not([tabsintitlebar]) .titlebar-placeholder {
|
||||
|
|
|
@ -4481,6 +4481,9 @@ var TabsInTitlebar = {
|
|||
// Try to avoid reflows in this code by calculating dimensions first and
|
||||
// then later set the properties affecting layout together in a batch.
|
||||
|
||||
// Get the full height of the tabs toolbar:
|
||||
let tabsToolbar = $("TabsToolbar");
|
||||
let fullTabsHeight = rect(tabsToolbar).height;
|
||||
// Buttons first:
|
||||
let captionButtonsBoxWidth = rect($("titlebar-buttonbox")).width;
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -4495,11 +4498,9 @@ var TabsInTitlebar = {
|
|||
let menuHeight = rect(menubar).height;
|
||||
let menuStyles = window.getComputedStyle(menubar);
|
||||
let fullMenuHeight = verticalMargins(menuStyles) + menuHeight;
|
||||
#endif
|
||||
// Get the full height of the tabs toolbar:
|
||||
let tabsToolbar = $("TabsToolbar");
|
||||
let tabsStyles = window.getComputedStyle(tabsToolbar);
|
||||
let fullTabsHeight = rect(tabsToolbar).height + verticalMargins(tabsStyles);
|
||||
fullTabsHeight += verticalMargins(tabsStyles);
|
||||
#endif
|
||||
|
||||
// If the navbar overlaps the tabbar using negative margins, we need to take those into
|
||||
// account so we don't overlap it
|
||||
|
@ -4509,16 +4510,6 @@ var TabsInTitlebar = {
|
|||
// And get the height of what's in the titlebar:
|
||||
let titlebarContentHeight = rect(titlebarContent).height;
|
||||
|
||||
// Padding surrounds the tab-view-deck when we are in customization mode,
|
||||
// so take that into account:
|
||||
let areCustomizing = document.documentElement.hasAttribute("customizing") ||
|
||||
document.documentElement.hasAttribute("customize-exiting");
|
||||
let customizePadding = 0;
|
||||
if (areCustomizing) {
|
||||
let deckStyle = window.getComputedStyle($("tab-view-deck"));
|
||||
customizePadding = parseFloat(deckStyle.paddingTop);
|
||||
}
|
||||
|
||||
// Begin setting CSS properties which will cause a reflow
|
||||
|
||||
// If the menubar is around (menuHeight is non-zero), try to adjust
|
||||
|
@ -4551,10 +4542,6 @@ var TabsInTitlebar = {
|
|||
// Next, we calculate how much we need to stretch the titlebar down to
|
||||
// go all the way to the bottom of the tab strip, if necessary.
|
||||
let tabAndMenuHeight = fullTabsHeight + fullMenuHeight;
|
||||
// Oh, and don't forget customization mode:
|
||||
if (areCustomizing) {
|
||||
tabAndMenuHeight += customizePadding;
|
||||
}
|
||||
|
||||
if (tabAndMenuHeight > titlebarContentHeight) {
|
||||
// We need to increase the titlebar content's outer height (ie including margins)
|
||||
|
@ -4566,12 +4553,6 @@ var TabsInTitlebar = {
|
|||
// On non-OSX, we can just use bottom margin:
|
||||
#ifndef XP_MACOSX
|
||||
titlebarContent.style.marginBottom = extraMargin + "px";
|
||||
#else
|
||||
// Otherwise, center the content. This means taking the titlebar's
|
||||
// padding into account:
|
||||
let halfMargin = (extraMargin - titlebarPadding) / 2;
|
||||
titlebarContent.style.marginTop = halfMargin + "px";
|
||||
titlebarContent.style.marginBottom = (titlebarPadding + halfMargin) + "px";
|
||||
#endif
|
||||
titlebarContentHeight += extraMargin;
|
||||
}
|
||||
|
@ -4606,6 +4587,7 @@ var TabsInTitlebar = {
|
|||
updateTitlebarDisplay();
|
||||
|
||||
// Reset the margins and padding that might have been modified:
|
||||
titlebarContent.style.marginTop = "";
|
||||
titlebarContent.style.marginBottom = "";
|
||||
titlebar.style.marginBottom = "";
|
||||
menubar.style.paddingBottom = "";
|
||||
|
@ -4630,16 +4612,37 @@ var TabsInTitlebar = {
|
|||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
function updateTitlebarDisplay() {
|
||||
document.getElementById("titlebar").hidden = !TabsInTitlebar.enabled;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// OS X and the other platforms differ enough to necessitate this kind of
|
||||
// special-casing. Like the other platforms where we CAN_DRAW_IN_TITLEBAR,
|
||||
// we draw in the OS X titlebar when putting the tabs up there. However, OS X
|
||||
// also draws in the titlebar when a lightweight theme is applied, regardless
|
||||
// of whether or not the tabs are drawn in the titlebar.
|
||||
if (TabsInTitlebar.enabled) {
|
||||
document.documentElement.setAttribute("chromemargin-nonlwtheme", "0,-1,-1,-1");
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
document.documentElement.removeAttribute("drawtitle");
|
||||
} else {
|
||||
// We set chromemargin-nonlwtheme to "" instead of removing it as a way of
|
||||
// making sure that LightweightThemeConsumer doesn't take it upon itself to
|
||||
// detect this value again if and when we do a lwtheme state change.
|
||||
document.documentElement.setAttribute("chromemargin-nonlwtheme", "");
|
||||
let isCustomizing = document.documentElement.hasAttribute("customizing");
|
||||
let hasLWTheme = document.documentElement.hasAttribute("lwtheme");
|
||||
if (!hasLWTheme || isCustomizing) {
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
}
|
||||
document.documentElement.setAttribute("drawtitle", "true");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (TabsInTitlebar.enabled)
|
||||
#ifdef XP_WIN
|
||||
document.documentElement.setAttribute("chromemargin", "0,2,2,2");
|
||||
#else
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
#endif
|
||||
else
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -313,7 +313,8 @@ skip-if = true # disabled until the tree view is added
|
|||
[browser_tab_dragdrop.js]
|
||||
[browser_tab_dragdrop2.js]
|
||||
[browser_tabbar_big_widgets.js]
|
||||
skip-if = os == "linux" # No tabs in titlebar on linux
|
||||
skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
|
||||
# Disabled on OS X because of bug 967917
|
||||
[browser_tabfocus.js]
|
||||
[browser_tabopen_reflows.js]
|
||||
[browser_tabs_isActive.js]
|
||||
|
|
|
@ -123,9 +123,6 @@ const CustomizableWidgets = [{
|
|||
item.setAttribute("label", title || uri);
|
||||
item.setAttribute("targetURI", uri);
|
||||
item.setAttribute("class", "subviewbutton");
|
||||
item.addEventListener("command", function (aEvent) {
|
||||
onHistoryVisit(uri, aEvent, item);
|
||||
});
|
||||
item.addEventListener("click", function (aEvent) {
|
||||
onHistoryVisit(uri, aEvent, item);
|
||||
});
|
||||
|
|
|
@ -13,6 +13,8 @@ support-files =
|
|||
# Bug 916763 - too many intermittent failures
|
||||
skip-if = true
|
||||
[browser_inspector_markup_edit.js]
|
||||
# Bug 904953 - too many intermittent failures on Linux
|
||||
skip-if = os == "linux"
|
||||
[browser_inspector_markup_edit_outerhtml.js]
|
||||
[browser_inspector_markup_edit_outerhtml2.js]
|
||||
[browser_inspector_markup_mutation.js]
|
||||
|
|
|
@ -1143,8 +1143,7 @@ var BrowserUI = {
|
|||
confirmSanitizeDialog: function () {
|
||||
let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
|
||||
let title = bundle.GetStringFromName("clearPrivateData.title2");
|
||||
let options = bundle.GetStringFromName("optionsCharm");
|
||||
let message = bundle.GetStringFromName("clearPrivateData.message2").replace("#1", options);
|
||||
let message = bundle.GetStringFromName("clearPrivateData.message3");
|
||||
let clearbutton = bundle.GetStringFromName("clearPrivateData.clearButton");
|
||||
|
||||
let prefsClearButton = document.getElementById("prefs-clear-data");
|
||||
|
|
|
@ -9,16 +9,18 @@ function test() {
|
|||
runTests();
|
||||
}
|
||||
|
||||
function getSimpleMeasurementsFromTelemetryPing() {
|
||||
function getTelemetryPayload() {
|
||||
return Cu.import("resource://gre/modules/TelemetryPing.jsm", {}).
|
||||
TelemetryPing.getPayload().simpleMeasurements;
|
||||
TelemetryPing.getPayload();
|
||||
}
|
||||
|
||||
gTests.push({
|
||||
desc: "Test browser-ui telemetry",
|
||||
run: function testBrowserUITelemetry() {
|
||||
// startup should have registered simple measures function
|
||||
let simpleMeasurements = getSimpleMeasurementsFromTelemetryPing();
|
||||
is(getTelemetryPayload().info.appName, "MetroFirefox");
|
||||
|
||||
let simpleMeasurements = getTelemetryPayload().simpleMeasurements;
|
||||
ok(simpleMeasurements, "simpleMeasurements are truthy");
|
||||
ok(simpleMeasurements.UITelemetry["metro-ui"]["window-width"], "window-width measurement was captured");
|
||||
ok(simpleMeasurements.UITelemetry["metro-ui"]["window-height"], "window-height measurement was captured");
|
||||
|
|
|
@ -39,8 +39,8 @@ contextAppbar2.clear=Clear selection
|
|||
# Clear private data
|
||||
clearPrivateData.clearButton=Clear
|
||||
clearPrivateData.title2=Clear private data
|
||||
# LOCALIZATION NOTE (clearPrivateData.message2): #1 is optionsCharm
|
||||
clearPrivateData.message2=This will permanently delete the private data you have selected in #1
|
||||
# LOCALIZATION NOTE (clearPrivateData.message3): "Options" is the optionsCharm.
|
||||
clearPrivateData.message3=This will permanently delete the private data you have selected in "Options".
|
||||
|
||||
# Settings Charms
|
||||
aboutCharm1=About
|
||||
|
|
|
@ -73,6 +73,7 @@ browser.jar:
|
|||
skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
|
||||
skin/classic/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
|
||||
skin/classic/browser/customizableui/customizeFavicon.ico (../shared/customizableui/customizeFavicon.ico)
|
||||
skin/classic/browser/customizableui/menuPanel-customizeFinish.png (../shared/customizableui/menuPanel-customizeFinish.png)
|
||||
* skin/classic/browser/customizableui/panelUIOverlay.css (customizableui/panelUIOverlay.css)
|
||||
skin/classic/browser/customizableui/subView-arrow-back-inverted.png (../shared/customizableui/subView-arrow-back-inverted.png)
|
||||
skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#main-window[chromehidden~="toolbar"] > #titlebar {
|
||||
#main-window[chromehidden~="toolbar"]:not(:-moz-lwtheme) > #titlebar {
|
||||
padding-top: 22px;
|
||||
}
|
||||
|
||||
|
@ -2669,7 +2669,7 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
|||
box-shadow: @focusRingShadow@;
|
||||
}
|
||||
|
||||
#titlebar {
|
||||
#main-window:not(:-moz-lwtheme) > #titlebar {
|
||||
padding-top: @spaceAboveTabbar@;
|
||||
min-height: @tabHeight@;
|
||||
}
|
||||
|
@ -4104,13 +4104,26 @@ window > chatbox {
|
|||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
||||
#main-window[customize-entered] #titlebar {
|
||||
#main-window[customize-entered] > #titlebar {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar][customize-entered] #titlebar-content {
|
||||
margin-bottom: 0px !important;
|
||||
margin-top: 11px !important;
|
||||
#main-window[tabsintitlebar]:not([customizing]):not(:-moz-lwtheme) > #titlebar > #titlebar-content,
|
||||
#main-window[tabsintitlebar][customize-entering] > #titlebar > #titlebar-content,
|
||||
#main-window[tabsintitlebar][customize-exiting] > #titlebar > #titlebar-content {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar][customize-entered] > #titlebar > #titlebar-content,
|
||||
#main-window:not([tabsintitlebar]):not(:-moz-lwtheme) > #titlebar > #titlebar-content {
|
||||
margin-top: 11px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
#main-window[tabsintitlebar]:-moz-lwtheme > #titlebar > #titlebar-content {
|
||||
margin-top: 11px;
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #tab-view-deck {
|
||||
|
@ -4135,8 +4148,11 @@ window > chatbox {
|
|||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #TabsToolbar {
|
||||
#main-window[tabsintitlebar][customize-entered] #TabsToolbar {
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #TabsToolbar {
|
||||
background-clip: padding-box;
|
||||
border-right: 3px solid transparent;
|
||||
border-left: 3px solid transparent;
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
list-style-image: url(chrome://browser/skin/menuPanel-customize@2x.png);
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #PanelUI-customize {
|
||||
list-style-image: url(chrome://browser/skin/customizableui/menuPanel-customizeFinish@2x.png);
|
||||
}
|
||||
|
||||
#PanelUI-help {
|
||||
list-style-image: url(chrome://browser/skin/menuPanel-help@2x.png);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ browser.jar:
|
|||
skin/classic/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
|
||||
skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
|
||||
skin/classic/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
|
||||
skin/classic/browser/customizableui/menuPanel-customizeFinish.png (../shared/customizableui/menuPanel-customizeFinish.png)
|
||||
skin/classic/browser/customizableui/menuPanel-customizeFinish@2x.png (../shared/customizableui/menuPanel-customizeFinish@2x.png)
|
||||
skin/classic/browser/customizableui/subView-arrow-back-inverted.png (../shared/customizableui/subView-arrow-back-inverted.png)
|
||||
skin/classic/browser/customizableui/subView-arrow-back-inverted@2x.png (../shared/customizableui/subView-arrow-back-inverted@2x.png)
|
||||
* skin/classic/browser/customizableui/panelUIOverlay.css (customizableui/panelUIOverlay.css)
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 236 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 399 B |
|
@ -322,6 +322,10 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
|||
list-style-image: url(chrome://browser/skin/menuPanel-customize.png);
|
||||
}
|
||||
|
||||
#customization-panelHolder #PanelUI-customize {
|
||||
list-style-image: url(chrome://browser/skin/customizableui/menuPanel-customizeFinish.png);
|
||||
}
|
||||
|
||||
#PanelUI-help {
|
||||
list-style-image: url(chrome://browser/skin/menuPanel-help.png);
|
||||
}
|
||||
|
@ -378,16 +382,15 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
|||
background-color: #ad3434;
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #PanelUI-customize {
|
||||
#customization-panelHolder #PanelUI-customize {
|
||||
color: white;
|
||||
background-image: linear-gradient(rgb(41,123,204), rgb(40,133,203));
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,0.5), 0 2px rgba(255,255,255,0.2);
|
||||
text-shadow: 0 1px 0 rgba(0,0,0,0.4);
|
||||
background-color: rgb(116,191,67);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
#main-window[customize-entered] #PanelUI-customize:hover,
|
||||
#main-window[customize-entered] #PanelUI-customize:hover:active {
|
||||
background-image: linear-gradient(rgb(38,115,191), rgb(38,125,191));
|
||||
#customization-panelHolder #PanelUI-customize:hover,
|
||||
#customization-panelHolder #PanelUI-customize:hover:active {
|
||||
background-color: rgb(105,173,61);
|
||||
}
|
||||
|
||||
#customization-palette .toolbarbutton-multiline-text,
|
||||
|
|
|
@ -92,6 +92,7 @@ browser.jar:
|
|||
skin/classic/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
|
||||
skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
|
||||
skin/classic/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
|
||||
skin/classic/browser/customizableui/menuPanel-customizeFinish.png (../shared/customizableui/menuPanel-customizeFinish.png)
|
||||
* skin/classic/browser/customizableui/panelUIOverlay.css (customizableui/panelUIOverlay.css)
|
||||
skin/classic/browser/customizableui/subView-arrow-back-inverted.png (../shared/customizableui/subView-arrow-back-inverted.png)
|
||||
* skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
|
||||
|
@ -404,6 +405,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/customizableui/customizeMode-gridTexture.png (customizableui/customizeMode-gridTexture.png)
|
||||
skin/classic/aero/browser/customizableui/customizeMode-separatorHorizontal.png (customizableui/customizeMode-separatorHorizontal.png)
|
||||
skin/classic/aero/browser/customizableui/customizeMode-separatorVertical.png (customizableui/customizeMode-separatorVertical.png)
|
||||
skin/classic/aero/browser/customizableui/menuPanel-customizeFinish.png (../shared/customizableui/menuPanel-customizeFinish.png)
|
||||
* skin/classic/aero/browser/customizableui/panelUIOverlay.css (customizableui/panelUIOverlay.css)
|
||||
skin/classic/aero/browser/customizableui/subView-arrow-back-inverted.png (../shared/customizableui/subView-arrow-back-inverted.png)
|
||||
* skin/classic/aero/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay-aero.css)
|
||||
|
|
|
@ -538,7 +538,7 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
this.fieldID = integerQuery("named_fields", "field_id",
|
||||
"measurement_name = ? AND measurement_version = ? AND field_name = ?",
|
||||
new String[] {measurementName, measurementVersion, fieldName},
|
||||
-1);
|
||||
UNKNOWN_TYPE_OR_FIELD_ID);
|
||||
if (this.fieldID == UNKNOWN_TYPE_OR_FIELD_ID) {
|
||||
throw new IllegalStateException("No field with name " + fieldName +
|
||||
" (" + measurementName + ", " + measurementVersion + ")");
|
||||
|
@ -552,7 +552,9 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
// store differently stable kinds of data, hence type difference.
|
||||
// Note that we don't pre-populate the environment cache. We'll typically only
|
||||
// handle one per session.
|
||||
private final ConcurrentHashMap<String, Integer> envs = new ConcurrentHashMap<String, Integer>();
|
||||
//
|
||||
// protected for testing purposes only.
|
||||
protected final ConcurrentHashMap<String, Integer> envs = new ConcurrentHashMap<String, Integer>();
|
||||
|
||||
/**
|
||||
* An {@link Environment} that knows how to persist to and from our database.
|
||||
|
@ -855,6 +857,12 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
private HashMap<String, Field> fields = new HashMap<String, Field>();
|
||||
private boolean fieldsCacheUpdated = false;
|
||||
|
||||
private void invalidateFieldsCache() {
|
||||
synchronized (this.fields) {
|
||||
fieldsCacheUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldKey(String mName, int mVersion, String fieldName) {
|
||||
return mVersion + "." + mName + "/" + fieldName;
|
||||
}
|
||||
|
@ -1014,9 +1022,7 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
notifyMeasurementVersionUpdated(measurement, version);
|
||||
|
||||
// Let's be easy for now.
|
||||
synchronized (fields) {
|
||||
fieldsCacheUpdated = false;
|
||||
}
|
||||
invalidateFieldsCache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1152,10 +1158,16 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
|
||||
final SQLiteDatabase db = this.helper.getWritableDatabase();
|
||||
putValue(v, value);
|
||||
try {
|
||||
db.insertOrThrow(table, null, v);
|
||||
} catch (SQLiteConstraintException e) {
|
||||
throw new IllegalStateException("Event did not reference existing an environment or field.", e);
|
||||
|
||||
// Using SQLiteDatabase.insertOrThrow throws SQLiteConstraintException we cannot catch for
|
||||
// unknown reasons (bug 961526 comment 13). We believe these are thrown because we attempt to
|
||||
// record events using environment IDs removed from the database by the prune service. We
|
||||
// invalidate the currentEnvironment ID after pruning, preventing further propagation,
|
||||
// however, any event recording waiting for the prune service to complete on the background
|
||||
// thread may carry an invalid ID: we expect an insertion failure and drop these events here.
|
||||
final long res = db.insert(table, null, v);
|
||||
if (res == -1) {
|
||||
Logger.error(LOG_TAG, "Unable to record daily discrete event. Ignoring.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1516,6 +1528,11 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
try {
|
||||
// Cascade will clear the rest.
|
||||
db.delete("measurements", null, null);
|
||||
|
||||
// Clear measurements and fields cache, because some of their IDs are now invalid.
|
||||
invalidateFieldsCache(); // Let it repopulate on its own.
|
||||
populateMeasurementVersionsCache(db); // Performed at Storage init so repopulate now.
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@ -1524,7 +1541,7 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
|
||||
/**
|
||||
* Prunes the given number of least-recently used environments. Note that orphaned environments
|
||||
* are not removed.
|
||||
* are not removed and the environment cache is cleared.
|
||||
*/
|
||||
public void pruneEnvironments(final int numToPrune) {
|
||||
final SQLiteDatabase db = this.helper.getWritableDatabase();
|
||||
|
@ -1538,6 +1555,9 @@ public class HealthReportDatabaseStorage implements HealthReportStorage {
|
|||
" LIMIT " + numToPrune + ")",
|
||||
null);
|
||||
db.setTransactionSuccessful();
|
||||
|
||||
// Clear environment cache, because some of their IDs are now invalid.
|
||||
this.envs.clear();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,11 @@ public class PrunePolicyDatabaseStorage implements PrunePolicyStorage {
|
|||
|
||||
public void pruneEnvironments(final int count) {
|
||||
getStorage().pruneEnvironments(count);
|
||||
|
||||
// Re-populate the DB and environment cache with the current environment in the unlikely event
|
||||
// that it was deleted.
|
||||
this.currentEnvironmentID = -1;
|
||||
getCurrentEnvironmentID();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,9 +37,13 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
|
@ -758,11 +762,11 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
public static final String MEASUREMENT_NAME_SEARCH_COUNTS = "org.mozilla.searches.counts";
|
||||
public static final int MEASUREMENT_VERSION_SEARCH_COUNTS = 5;
|
||||
|
||||
public static final String[] SEARCH_LOCATIONS = {
|
||||
public static final Set<String> SEARCH_LOCATIONS = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(new String[] {
|
||||
"barkeyword",
|
||||
"barsuggest",
|
||||
"bartext",
|
||||
};
|
||||
})));
|
||||
|
||||
private void initializeSearchProvider() {
|
||||
this.storage.ensureMeasurementInitialized(
|
||||
|
@ -771,7 +775,7 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
new MeasurementFields() {
|
||||
@Override
|
||||
public Iterable<FieldSpec> getFields() {
|
||||
ArrayList<FieldSpec> out = new ArrayList<FieldSpec>(SEARCH_LOCATIONS.length);
|
||||
ArrayList<FieldSpec> out = new ArrayList<FieldSpec>(SEARCH_LOCATIONS.size());
|
||||
for (String location : SEARCH_LOCATIONS) {
|
||||
// We're not using a counter, because the set of engine
|
||||
// identifiers is potentially unbounded, and thus our
|
||||
|
@ -803,19 +807,31 @@ public class BrowserHealthRecorder implements GeckoEventListener {
|
|||
return;
|
||||
}
|
||||
|
||||
final int env = this.env;
|
||||
|
||||
if (env == -1) {
|
||||
Log.d(LOG_TAG, "No environment: not recording search.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (location == null) {
|
||||
throw new IllegalArgumentException("location must be provided for search.");
|
||||
}
|
||||
|
||||
// Ensure that we don't throw when trying to look up the field for an
|
||||
// unknown location. If you add a search location, you must extend the
|
||||
// list of search locations *and update the measurement version*.
|
||||
if (!SEARCH_LOCATIONS.contains(location)) {
|
||||
throw new IllegalArgumentException("Unexpected location: " + location);
|
||||
}
|
||||
|
||||
final int day = storage.getDay();
|
||||
final int env = this.env;
|
||||
final String key = (engineID == null) ? "other" : engineID;
|
||||
final BrowserHealthRecorder self = this;
|
||||
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final HealthReportDatabaseStorage storage = self.storage;
|
||||
final HealthReportDatabaseStorage storage = BrowserHealthRecorder.this.storage;
|
||||
if (storage == null) {
|
||||
Log.d(LOG_TAG, "No storage: not recording search. Shutting down?");
|
||||
return;
|
||||
|
|
|
@ -5,6 +5,7 @@ package org.mozilla.gecko.background.healthreport;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
|
@ -42,6 +43,10 @@ public class MockHealthReportDatabaseStorage extends HealthReportDatabaseStorage
|
|||
return now - numDays * GlobalConstants.MILLISECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, Integer> getEnvironmentCache() {
|
||||
return this.envs;
|
||||
}
|
||||
|
||||
public MockHealthReportDatabaseStorage(Context context, File fakeProfileDirectory) {
|
||||
super(context, fakeProfileDirectory);
|
||||
}
|
||||
|
|
|
@ -326,10 +326,6 @@ public class TestHealthReportDatabaseStorage extends FakeProfileTestCase {
|
|||
storage.incrementDailyCount(nonExistentEnvID, storage.getToday(), counterFieldID);
|
||||
fail("Should throw - event_integer(env) references environments(id), which is given as a non-existent value.");
|
||||
} catch (IllegalStateException e) { }
|
||||
try {
|
||||
storage.recordDailyDiscrete(nonExistentEnvID, storage.getToday(), discreteFieldID, "iu");
|
||||
fail("Should throw - event_textual(env) references environments(id), which is given as a non-existent value.");
|
||||
} catch (IllegalStateException e) { }
|
||||
try {
|
||||
storage.recordDailyLast(nonExistentEnvID, storage.getToday(), discreteFieldID, "iu");
|
||||
fail("Should throw - event_textual(env) references environments(id), which is given as a non-existent value.");
|
||||
|
@ -339,14 +335,30 @@ public class TestHealthReportDatabaseStorage extends FakeProfileTestCase {
|
|||
storage.incrementDailyCount(envID, storage.getToday(), nonExistentFieldID);
|
||||
fail("Should throw - event_integer(field) references fields(id), which is given as a non-existent value.");
|
||||
} catch (IllegalStateException e) { }
|
||||
try {
|
||||
storage.recordDailyDiscrete(envID, storage.getToday(), nonExistentFieldID, "iu");
|
||||
fail("Should throw - event_textual(field) references fields(id), which is given as a non-existent value.");
|
||||
} catch (IllegalStateException e) { }
|
||||
try {
|
||||
storage.recordDailyLast(envID, storage.getToday(), nonExistentFieldID, "iu");
|
||||
fail("Should throw - event_textual(field) references fields(id), which is given as a non-existent value.");
|
||||
} catch (IllegalStateException e) { }
|
||||
|
||||
// Test dropped events due to constraint violations that do not throw (see bug 961526).
|
||||
final String eventValue = "a value not in the database";
|
||||
assertFalse(isEventInDB(db, eventValue)); // Better safe than sorry.
|
||||
|
||||
storage.recordDailyDiscrete(nonExistentEnvID, storage.getToday(), discreteFieldID, eventValue);
|
||||
assertFalse(isEventInDB(db, eventValue));
|
||||
|
||||
storage.recordDailyDiscrete(envID, storage.getToday(), nonExistentFieldID, "iu");
|
||||
assertFalse(isEventInDB(db, eventValue));
|
||||
}
|
||||
|
||||
private static boolean isEventInDB(final SQLiteDatabase db, final String value) {
|
||||
final Cursor c = db.query("events_textual", new String[] {"value"}, "value = ?",
|
||||
new String[] {value}, null, null, null);
|
||||
try {
|
||||
return c.getCount() > 0;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Largely taken from testDeleteEnvAndEventsBefore and testDeleteOrphanedAddons.
|
||||
|
@ -553,7 +565,10 @@ public class TestHealthReportDatabaseStorage extends FakeProfileTestCase {
|
|||
new PrepopulatedMockHealthReportDatabaseStorage(context, fakeProfileDirectory, 2);
|
||||
final SQLiteDatabase db = storage.getDB();
|
||||
assertEquals(5, DBHelpers.getRowCount(db, "environments"));
|
||||
assertEquals(5, storage.getEnvironmentCache().size());
|
||||
|
||||
storage.pruneEnvironments(1);
|
||||
assertEquals(0, storage.getEnvironmentCache().size());
|
||||
assertTrue(!getEnvAppVersions(db).contains("v3"));
|
||||
storage.pruneEnvironments(2);
|
||||
assertTrue(!getEnvAppVersions(db).contains("v2"));
|
||||
|
|
|
@ -457,6 +457,14 @@ let Impl = {
|
|||
revision: HISTOGRAMS_FILE_VERSION,
|
||||
locale: getLocale()
|
||||
};
|
||||
|
||||
// In order to share profile data, the appName used for Metro Firefox is "Firefox",
|
||||
// (the same as desktop Firefox). We set it to "MetroFirefox" here in order to
|
||||
// differentiate telemetry pings sent by desktop vs. metro Firefox.
|
||||
if(Services.metro && Services.metro.immersive) {
|
||||
ret.appName = "MetroFirefox";
|
||||
}
|
||||
|
||||
if (this._previousBuildID) {
|
||||
ret.previousBuildID = this._previousBuildID;
|
||||
}
|
||||
|
|
|
@ -42,9 +42,7 @@ LightweightThemeConsumer.prototype = {
|
|||
_lastScreenWidth: null,
|
||||
_lastScreenHeight: null,
|
||||
_enabled: true,
|
||||
#ifdef XP_MACOSX
|
||||
_chromemarginDefault: undefined,
|
||||
#endif
|
||||
_active: false,
|
||||
|
||||
enable: function() {
|
||||
this._enabled = true;
|
||||
|
@ -100,8 +98,9 @@ LightweightThemeConsumer.prototype = {
|
|||
if (!this._enabled)
|
||||
return;
|
||||
|
||||
var root = this._doc.documentElement;
|
||||
var active = !!aData.headerURL;
|
||||
let root = this._doc.documentElement;
|
||||
let active = !!aData.headerURL;
|
||||
let stateChanging = (active != this._active);
|
||||
|
||||
if (active) {
|
||||
root.style.color = aData.textcolor || "black";
|
||||
|
@ -117,6 +116,8 @@ LightweightThemeConsumer.prototype = {
|
|||
root.removeAttribute("lwtheme");
|
||||
}
|
||||
|
||||
this._active = active;
|
||||
|
||||
_setImage(root, active, aData.headerURL);
|
||||
if (this._footerId) {
|
||||
let footer = this._doc.getElementById(this._footerId);
|
||||
|
@ -129,20 +130,26 @@ LightweightThemeConsumer.prototype = {
|
|||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Sample whether or not we draw in the titlebar by default the first time we update.
|
||||
// If the root has no chromemargin attribute, getAttribute will return null, and
|
||||
// we'll remove the attribute when the lw-theme is deactivated.
|
||||
if (this._chromemarginDefault === undefined)
|
||||
this._chromemarginDefault = root.getAttribute("chromemargin");
|
||||
// On OS X, we extend the lightweight theme into the titlebar, which means setting
|
||||
// the chromemargin attribute. Some XUL applications already draw in the titlebar,
|
||||
// so we need to save the chromemargin value before we overwrite it with the value
|
||||
// that lets us draw in the titlebar. We stash this value on the root attribute so
|
||||
// that XUL applications have the ability to invalidate the saved value.
|
||||
if (stateChanging) {
|
||||
if (!root.hasAttribute("chromemargin-nonlwtheme")) {
|
||||
root.setAttribute("chromemargin-nonlwtheme", root.getAttribute("chromemargin"));
|
||||
}
|
||||
|
||||
if (active) {
|
||||
root.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
}
|
||||
else {
|
||||
if (this._chromemarginDefault)
|
||||
root.setAttribute("chromemargin", this._chromemarginDefault);
|
||||
else
|
||||
root.removeAttribute("chromemargin");
|
||||
if (active) {
|
||||
root.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
} else {
|
||||
let defaultChromemargin = root.getAttribute("chromemargin-nonlwtheme");
|
||||
if (defaultChromemargin) {
|
||||
root.setAttribute("chromemargin", defaultChromemargin);
|
||||
} else {
|
||||
root.removeAttribute("chromemargin");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче