merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-06-28 16:06:34 +02:00
commit faeec86517
57 changed files with 579 additions and 270 deletions

View File

@ -54,7 +54,7 @@ DEFAULT_NO_CONNECTIONS_PREFS = {
'browser.newtab.url' : 'about:blank',
'browser.search.update': False,
'browser.search.suggest.enabled' : False,
'browser.safebrowsing.enabled' : False,
'browser.safebrowsing.phishing.enabled' : False,
'browser.safebrowsing.provider.google.updateURL': 'http://localhost/safebrowsing-dummy/update',
'browser.safebrowsing.provider.google.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
'browser.safebrowsing.malware.reportURL': 'http://localhost/safebrowsing-dummy/malwarereport',

View File

@ -14,7 +14,7 @@
"browser.newtab.url": "about:blank",
"browser.search.update": false,
"browser.search.suggest.enabled": false,
"browser.safebrowsing.enabled": false,
"browser.safebrowsing.phishing.enabled": false,
"browser.safebrowsing.provider.google.updateURL": "http://localhost/safebrowsing-dummy/update",
"browser.safebrowsing.provider.google.gethashURL": "http://localhost/safebrowsing-dummy/gethash",
"browser.safebrowsing.provider.google.reportURL": "http://localhost/safebrowsing-dummy/malwarereport",

View File

@ -611,7 +611,7 @@ var settingsToObserve = {
},
'app.update.interval': 86400,
'apz.overscroll.enabled': true,
'browser.safebrowsing.enabled': true,
'browser.safebrowsing.phishing.enabled': true,
'browser.safebrowsing.malware.enabled': true,
'debug.fps.enabled': {
prefName: 'layers.acceleration.draw-fps',

View File

@ -1014,13 +1014,14 @@ pref("services.sync.prefs.sync.addons.ignoreUserEnabledChanges", true);
// could weaken the pref locally, install an add-on from an untrusted
// source, and this would propagate automatically to other,
// uncompromised Sync-connected devices.
pref("services.sync.prefs.sync.browser.download.useDownloadDir", true);
pref("services.sync.prefs.sync.browser.formfill.enable", true);
pref("services.sync.prefs.sync.browser.link.open_newwindow", true);
pref("services.sync.prefs.sync.browser.newtabpage.enabled", true);
pref("services.sync.prefs.sync.browser.newtabpage.enhanced", true);
pref("services.sync.prefs.sync.browser.newtabpage.pinned", true);
pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
pref("services.sync.prefs.sync.browser.safebrowsing.enabled", true);
pref("services.sync.prefs.sync.browser.safebrowsing.phishing.enabled", true);
pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true);
pref("services.sync.prefs.sync.browser.search.update", true);
pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);

View File

@ -410,14 +410,6 @@ const gSessionHistoryObserver = {
}
};
const gPermissionObserver = {
observe: function(subject, topic, data) {
if (topic === "perm-changed") {
gIdentityHandler.refreshIdentityBlock();
}
}
};
/**
* Given a starting docshell and a URI to look up, find the docshell the URI
* is loaded in.
@ -1168,7 +1160,7 @@ var gBrowserInit = {
setTimeout(function() { SafeBrowsing.init(); }, 2000);
}
Services.obs.addObserver(gPermissionObserver, "perm-changed", false);
Services.obs.addObserver(gIdentityHandler, "perm-changed", false);
Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
@ -1492,7 +1484,7 @@ var gBrowserInit = {
gBrowserThumbnails.uninit();
FullZoom.destroy();
Services.obs.removeObserver(gPermissionObserver, "perm-changed");
Services.obs.removeObserver(gIdentityHandler, "perm-changed");
Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-disabled");
Services.obs.removeObserver(gXPInstallObserver, "addon-install-started");
@ -7181,6 +7173,12 @@ var gIdentityHandler = {
}
},
observe(subject, topic, data) {
if (topic == "perm-changed") {
this.refreshIdentityBlock();
}
},
onDragStart: function (event) {
if (gURLBar.getAttribute("pageproxystate") != "valid")
return;

View File

@ -1927,7 +1927,7 @@ BrowserGlue.prototype = {
},
_migrateUI: function BG__migrateUI() {
const UI_VERSION = 39;
const UI_VERSION = 40;
const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
let currentUIVersion;
@ -2238,6 +2238,21 @@ BrowserGlue.prototype = {
xulStore.removeValue(BROWSER_DOCURL, toolbarId, "defaultset");
}
}
if (currentUIVersion < 40) {
const kOldSafeBrowsingPref = "browser.safebrowsing.enabled";
// Default value is set to true, a user pref means that the pref was
// set to false.
if (Services.prefs.prefHasUserValue(kOldSafeBrowsingPref) &&
!Services.prefs.getBoolPref(kOldSafeBrowsingPref)) {
Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled",
false);
// Should just remove support for the pref entirely, even if it's
// only in about:config
Services.prefs.clearUserPref(kOldSafeBrowsingPref);
}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
},

View File

@ -153,7 +153,7 @@ var gSecurityPane = {
let blockDownloads = document.getElementById("blockDownloads");
let blockUncommonUnwanted = document.getElementById("blockUncommonUnwanted");
let safeBrowsingPhishingPref = document.getElementById("browser.safebrowsing.enabled");
let safeBrowsingPhishingPref = document.getElementById("browser.safebrowsing.phishing.enabled");
let safeBrowsingMalwarePref = document.getElementById("browser.safebrowsing.malware.enabled");
let blockDownloadsPref = document.getElementById("browser.safebrowsing.downloads.enabled");

View File

@ -24,8 +24,8 @@
<preference id="browser.safebrowsing.malware.enabled"
name="browser.safebrowsing.malware.enabled"
type="bool"/>
<preference id="browser.safebrowsing.enabled"
name="browser.safebrowsing.enabled"
<preference id="browser.safebrowsing.phishing.enabled"
name="browser.safebrowsing.phishing.enabled"
type="bool"/>
<preference id="browser.safebrowsing.downloads.enabled"

View File

@ -1,5 +1,5 @@
const PREFS = [
"browser.safebrowsing.enabled",
"browser.safebrowsing.phishing.enabled",
"browser.safebrowsing.malware.enabled",
"browser.safebrowsing.downloads.enabled",
@ -18,7 +18,7 @@ registerCleanupFunction(function() {
// test the safebrowsing preference
add_task(function*() {
function* checkPrefSwitch(val1, val2) {
Services.prefs.setBoolPref("browser.safebrowsing.enabled", val1);
Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled", val1);
Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", val2);
yield openPreferencesViaOpenPreferencesAPI("security", undefined, { leaveOpen: true });
@ -37,7 +37,7 @@ add_task(function*() {
EventUtils.synthesizeMouseAtCenter(checkbox, {}, gBrowser.selectedBrowser.contentWindow);
// check that both settings are now turned on or off
is(Services.prefs.getBoolPref("browser.safebrowsing.enabled"), !checked,
is(Services.prefs.getBoolPref("browser.safebrowsing.phishing.enabled"), !checked,
"safebrowsing.enabled is set correctly");
is(Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled"), !checked,
"safebrowsing.malware.enabled is set correctly");

View File

@ -650,7 +650,9 @@ this.UITour = {
string.data = value;
Services.prefs.setComplexValue("browser.uitour.treatment." + name,
Ci.nsISupportsString, string);
UITourHealthReport.recordTreatmentTag(name, value);
// The notification is only meant to be used in tests.
UITourHealthReport.recordTreatmentTag(name, value)
.then(() => this.notify("TreatmentTag:TelemetrySent"));
break;
}
@ -1256,9 +1258,26 @@ this.UITour = {
},
}];
}
let defaultIcon = "chrome://browser/skin/heartbeat-icon.svg";
let iconURL = defaultIcon;
try {
// Take the optional icon URL if specified
if (aOptions.iconURL) {
iconURL = new URL(aOptions.iconURL);
// For now, only allow chrome URIs.
if (iconURL.protocol != "chrome:") {
iconURL = defaultIcon;
throw new Error("Invalid protocol");
}
}
} catch (error) {
log.error("showHeartbeat: Invalid icon URL specified.");
}
// Create the notification. Prefix its ID to decrease the chances of collisions.
let notice = nb.appendNotification(aOptions.message, "heartbeat-" + aOptions.flowId,
"chrome://browser/skin/heartbeat-icon.svg",
iconURL,
nb.PRIORITY_INFO_HIGH, buttons,
(aEventType) => {
if (aEventType != "removed") {
@ -2163,15 +2182,15 @@ this.UITour.init();
*/
const UITourHealthReport = {
recordTreatmentTag: function(tag, value) {
TelemetryController.submitExternalPing("uitour-tag",
{
version: 1,
tagName: tag,
tagValue: value,
},
{
addClientId: true,
addEnvironment: true,
});
return TelemetryController.submitExternalPing("uitour-tag",
{
version: 1,
tagName: tag,
tagValue: value,
},
{
addClientId: true,
addEnvironment: true,
});
}
};

View File

@ -379,6 +379,9 @@ var tests = [
let ac = new TelemetryArchiveTesting.Checker();
yield ac.promiseInit();
yield gContentAPI.setTreatmentTag("foobar", "baz");
// Wait until the treatment telemetry is sent before looking in the archive.
yield BrowserTestUtils.waitForContentEvent(gTestTab.linkedBrowser, "mozUITourNotification", false,
event => event.detail.event === "TreatmentTag:TelemetrySent");
yield new Promise((resolve) => {
gContentAPI.getTreatmentTag("foobar", (data) => {
is(data.value, "baz", "set and retrieved treatmentTag");

View File

@ -205,6 +205,51 @@ add_UITour_task(function* test_heartbeat_stars_show() {
yield receivedExpectedPromise;
})
/**
* Check that the heartbeat UI correctly takes optional icon URL.
*/
add_UITour_task(function* test_heartbeat_take_optional_icon_URL() {
let flowId = "ui-ratefirefox-" + Math.random();
let engagementURL = "http://example.com";
let iconURL = "chrome://branding/content/icon48.png";
// We need to call |gContentAPI.observe| at least once to set a valid |notificationListener|
// in UITour-lib.js, otherwise no message will get propagated.
gContentAPI.observe(() => {});
let receivedExpectedPromise = promiseWaitExpectedNotifications(
["Heartbeat:NotificationOffered", "Heartbeat:NotificationClosed", "Heartbeat:TelemetrySent"]);
// Show the Heartbeat notification and wait for it to be displayed.
let shownPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationOffered");
gContentAPI.showHeartbeat("How would you rate Firefox?", "Thank you!", flowId, engagementURL, null, null, {
iconURL: iconURL
});
// Validate the returned timestamp.
let data = yield shownPromise;
validateTimestamp('Heartbeat:Offered', data.timestamp);
// Check the icon URL
let notification = getHeartbeatNotification(flowId);
is(notification.image, iconURL, "The optional icon URL is not taken correctly");
// Close the heartbeat notification.
let closedPromise = promiseWaitHeartbeatNotification("Heartbeat:NotificationClosed");
let pingSentPromise = promiseWaitHeartbeatNotification("Heartbeat:TelemetrySent");
cleanUpNotification(flowId);
data = yield closedPromise;
validateTimestamp('Heartbeat:NotificationClosed', data.timestamp);
data = yield pingSentPromise;
info("'Heartbeat:TelemetrySent' notification received");
checkTelemetry(data, flowId, ["offeredTS", "closedTS"]);
// This rejects whenever an unexpected notification is received.
yield receivedExpectedPromise;
})
/**
* Test that the heartbeat UI correctly works with null engagement URL.
*/

View File

@ -79,6 +79,7 @@ body.certerror #advancedButton {
#advancedPanelContainer {
position: absolute;
padding: 24px 0;
width: 100%;
}
.advanced-panel {
@ -109,6 +110,10 @@ span#hostname {
#automaticallyReportInFuture {
cursor: pointer;
display: inline-block;
-moz-padding-start: 2.3em;
text-indent: -2.3em;
line-height: 16px
}
#errorCode:not([href]) {

View File

@ -1087,10 +1087,6 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
},
renderSourceSelected: function (source) {
// Set window title. No need to split the url by " -> " here,
// because it was already sanitized when the source was added.
document.title = L10N.getFormatStr("DebuggerWindowScriptTitle", source.url);
if (source.url) {
this._preferredSourceURL = source.url;
}

View File

@ -80,8 +80,6 @@ var DebuggerView = {
this._editorSource = {};
this._editorDocuments = {};
document.title = L10N.getStr("DebuggerWindowTitle");
this.editor.on("cursorActivity", this.Sources._onEditorCursorActivity);
this.controller = DebuggerController;

View File

@ -57,9 +57,6 @@ function test() {
is(gEditor.getText().search(/debugger/), 166,
"The second source is displayed. (1)");
ok(gDebugger.document.title.endsWith(EXAMPLE_URL + gLabel2),
"Title with second source is correct. (1)");
ok(isCaretPos(gPanel, 6),
"Editor caret location is correct. (1)");
@ -151,9 +148,6 @@ function test() {
}
Task.spawn(function* () {
ok(gDebugger.document.title.endsWith(EXAMPLE_URL + gLabel1),
"Title with first source is correct.");
const shown = waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1);
callInTab(gTab, "firstCall");
yield shown;

View File

@ -19,14 +19,6 @@ ToolboxDebugger.label=Debugger
# This is used as the label for the toolbox panel.
ToolboxDebugger.panelLabel=Debugger Panel
# LOCALIZATION NOTE (DebuggerWindowTitle):
# The title displayed for the debugger window.
DebuggerWindowTitle=Browser Debugger
# LOCALIZATION NOTE (DebuggerWindowScriptTitle):
# The title displayed for the debugger window when a script is selected.
DebuggerWindowScriptTitle=Browser Debugger - %S
# LOCALIZATION NOTE (ToolboxDebugger.tooltip2):
# This string is displayed in the tooltip of the tab when the debugger is
# displayed inside the developer tools window..

View File

@ -16,8 +16,11 @@ define(function (require, exports, module) {
const { PropRep } = createFactories(require("./prop-rep"));
// Shortcuts
const { span } = React.DOM;
/**
* @template TODO docs
* Renders generic grip. Grip is client representation
* of remote JS object and is used as an input object
* for this rep component.
*/
const Grip = React.createClass({
displayName: "Grip",
@ -139,7 +142,9 @@ define(function (require, exports, module) {
render: function () {
let object = this.props.object;
let props = this.shortPropIterator(object);
let props = (this.props.mode == "long") ?
this.longPropIterator(object) :
this.shortPropIterator(object);
if (this.props.mode == "tiny" || !props.length) {
return (
@ -159,6 +164,7 @@ define(function (require, exports, module) {
);
},
});
// Registration
function supportsObject(object, type) {
if (!isGrip(object)) {

View File

@ -98,10 +98,19 @@ window.onload = Task.async(function* () {
}
function testMoreThanMaxProps() {
// Test object = `{a: "a", b: "b", c: "c", d: "d", e: "e"}`
// Test object = `{p0: "0", p1: "1", p2: "2", ..., p101: "101"}`
const testName = "testMoreThanMaxProps";
const defaultOutput = `Object {a: "a", b: "b", c: "c", more...}`;
const defaultOutput = `Object {p0: "0", p1: "1", p2: "2", more...}`;
// Generate string with 100 properties, which is the max limit
// for 'long' mode.
let props = "";
for (let i = 0; i < 100; i++) {
props += "p" + i + ": \"" + i + "\", ";
}
const longOutput = `Object {${props}more...}`;
const modeTests = [
{
@ -116,11 +125,9 @@ window.onload = Task.async(function* () {
mode: "short",
expectedOutput: defaultOutput,
},
// @TODO Fix this test case.
// See Bug 1281489 - Reps: Grips rep renders only 3 properties in long mode
{
mode: "long",
expectedOutput: defaultOutput,
expectedOutput: longOutput,
}
];
@ -258,54 +265,37 @@ window.onload = Task.async(function* () {
}
};
case "testMoreThanMaxProps":
return {
case "testMoreThanMaxProps": {
let grip = {
"type": "object",
"class": "Object",
"actor": "server1.conn0.obj332",
"extensible": true,
"frozen": false,
"sealed": false,
"ownPropertyLength": 5,
"ownPropertyLength": 101,
"preview": {
"kind": "Object",
"ownProperties": {
"a": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": "a"
},
"b": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": "b"
},
"c": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": "c"
},
"d": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": "d"
},
"e": {
"configurable": true,
"enumerable": true,
"writable": true,
"value": "e"
}
},
"ownPropertiesLength": 5,
"ownProperties": {},
"ownPropertiesLength": 101,
"safeGetterValues": {}
}
};
// Generate 101 properties, which is more that the maximum
// limit in case of the 'long' mode.
for (let i = 0; i < 101; i++) {
grip.preview.ownProperties["p" + i] = {
"configurable": true,
"enumerable": true,
"writable": true,
"value": i + ""
};
}
return grip;
}
case "testUninterestingProps":
return {
"type": "object",

View File

@ -11,68 +11,69 @@
const TEST_URI = "data:text/html;charset=utf8,<p>hello world from bug 877778 " +
"<button onclick='foobar.explode()' " +
"style='test-color: green-please'>click!</button>";
function test() {
let hud;
loadTab(TEST_URI).then(() => {
HUDService.toggleBrowserConsole().then(browserConsoleOpened);
add_task(function* () {
yield new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [
["devtools.browserconsole.filter.cssparser", true]
]}, resolve);
});
function browserConsoleOpened(hudConsole) {
hud = hudConsole;
ok(hud, "browser console opened");
yield loadTab(TEST_URI);
let hud = yield HUDService.toggleBrowserConsole();
ok(hud, "browser console opened");
// On e10s, the exception is triggered in child process
// and is ignored by test harness
if (!Services.appinfo.browserTabsRemoteAutostart) {
expectUncaughtException();
}
info("generate exception and wait for the message");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
let button = content.document.querySelector("button");
button.click();
});
waitForMessages({
webconsole: hud,
messages: [
{
text: "ReferenceError: foobar is not defined",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
text: "Unknown property \u2018test-color\u2019",
category: CATEGORY_CSS,
severity: SEVERITY_WARNING,
},
],
}).then(onMessageFound);
// On e10s, the exception is triggered in child process
// and is ignored by test harness
if (!Services.appinfo.browserTabsRemoteAutostart) {
expectUncaughtException();
}
function onMessageFound(results) {
let viewSource = hud.viewSource;
let viewSourceCalled = false;
hud.viewSourceInDebugger = () => {
viewSourceCalled = true;
};
info("generate exception and wait for the message");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
let button = content.document.querySelector("button");
button.click();
});
for (let result of results) {
viewSourceCalled = false;
let results = yield waitForMessages({
webconsole: hud,
messages: [
{
text: "ReferenceError: foobar is not defined",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
text: "Unknown property \u2018test-color\u2019",
category: CATEGORY_CSS,
severity: SEVERITY_WARNING,
},
],
});
let msg = [...results[0].matched][0];
ok(msg, "message element found for: " + result.text);
let selector = ".message > .message-location .frame-link-filename";
let locationNode = msg.querySelector(selector);
ok(locationNode, "message location element found");
let viewSourceCalled = false;
EventUtils.synthesizeMouse(locationNode, 2, 2, {}, hud.iframeWindow);
let viewSource = hud.viewSource;
hud.viewSource = () => {
viewSourceCalled = true;
};
ok(viewSourceCalled, "view source opened");
}
for (let result of results) {
viewSourceCalled = false;
hud.viewSourceInDebugger = viewSource;
finishTest();
let msg = [...result.matched][0];
ok(msg, "message element found for: " + result.text);
ok(!msg.classList.contains("filtered-by-type"), "message element is not filtered");
let selector = ".message > .message-location .frame-link-source";
let locationNode = msg.querySelector(selector);
ok(locationNode, "message location element found");
EventUtils.synthesizeMouse(locationNode, 2, 2, {}, hud.iframeWindow);
ok(viewSourceCalled, "view source opened");
}
}
hud.viewSource = viewSource;
yield finishTest();
});

View File

@ -70,7 +70,7 @@ addEventListener('testready', function() {
SpecialPowers.pushPrefEnv({"set" : [
["privacy.trackingprotection.enabled", true],
["privacy.trackingprotection.pbmode.enabled", false],
["browser.safebrowsing.enabled", false],
["browser.safebrowsing.phishing.enabled", false],
["browser.safebrowsing.malware.enabled", false],
]}, () => {
SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);

View File

@ -23,7 +23,7 @@ user_pref("javascript.options.werror", false);
user_pref("toolkit.startup.max_resumed_crashes", -1);
user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
user_pref("toolkit.telemetry.enabled", false);
user_pref("browser.safebrowsing.enabled", false);
user_pref("browser.safebrowsing.phishing.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.safebrowsing.forbiddenURIs.enabled", false);
user_pref("browser.safebrowsing.blockedURIs.enabled", false);

View File

@ -79,7 +79,7 @@ user_pref("security.view-source.reachable-from-inner-protocol", true);
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.unified", false);
// Likewise for safebrowsing.
user_pref("browser.safebrowsing.enabled", false);
user_pref("browser.safebrowsing.phishing.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.safebrowsing.forbiddenURIs.enabled", false);
user_pref("browser.safebrowsing.blockedURIs.enabled", false);

View File

@ -619,6 +619,7 @@ public class Tabs implements GeckoEventListener {
BOOKMARK_ADDED,
BOOKMARK_REMOVED,
AUDIO_PLAYING_CHANGE,
OPENED_FROM_TABS_TRAY,
}
public void notifyListeners(Tab tab, TabEvents msg) {

View File

@ -20,7 +20,7 @@ public class URLMetadataTable extends BaseTable {
private static final int TABLE_ID_NUMBER = 1200;
// Uri for querying this table
static final Uri CONTENT_URI = Uri.withAppendedPath(BrowserContract.AUTHORITY_URI, "metadata");
public static final Uri CONTENT_URI = Uri.withAppendedPath(BrowserContract.AUTHORITY_URI, "metadata");
// Columns in the table
public static final String ID_COLUMN = "id";

View File

@ -72,6 +72,8 @@ public class OfflineTabStatusDelegate extends TabsTrayVisibilityAwareDelegate im
tabsQueuedForOfflineSnackbar.put(tab, null);
}
break;
// Fallthrough; see Bug 1278980 for details on why this event is here.
case OPENED_FROM_TABS_TRAY:
// When tab is selected and offline notification was queued, display it if possible.
// SELECTED event might also fire when we're on a TabStrip, so check first.
case SELECTED:

View File

@ -102,9 +102,13 @@ class TabsGridLayout extends GridView
setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TabsLayoutItemView tab = (TabsLayoutItemView) view;
Tabs.getInstance().selectTab(tab.getTabId());
final TabsLayoutItemView tab = (TabsLayoutItemView) view;
final int tabId = tab.getTabId();
Tabs.getInstance().selectTab(tabId);
autoHidePanel();
Tabs.getInstance().notifyListeners(
Tabs.getInstance().getTab(tabId), Tabs.TabEvents.OPENED_FROM_TABS_TRAY
);
}
});
@ -573,9 +577,13 @@ class TabsGridLayout extends GridView
mSwipeView.setPressed(false);
if (!mSwiping) {
TabsLayoutItemView item = (TabsLayoutItemView) mSwipeView;
Tabs.getInstance().selectTab(item.getTabId());
final TabsLayoutItemView item = (TabsLayoutItemView) mSwipeView;
final int tabId = item.getTabId();
Tabs.getInstance().selectTab(tabId);
autoHidePanel();
Tabs.getInstance().notifyListeners(
Tabs.getInstance().getTab(tabId), Tabs.TabEvents.OPENED_FROM_TABS_TRAY
);
mVelocityTracker.recycle();
mVelocityTracker = null;

View File

@ -496,8 +496,12 @@ class TabsListLayout extends TwoWayView
if (!swiping) {
TabsLayoutItemView item = (TabsLayoutItemView) swipeView;
Tabs.getInstance().selectTab(item.getTabId());
final int tabId = item.getTabId();
Tabs.getInstance().selectTab(tabId);
autoHidePanel();
Tabs.getInstance().notifyListeners(
Tabs.getInstance().getTab(tabId), Tabs.TabEvents.OPENED_FROM_TABS_TRAY
);
velocityTracker.recycle();
velocityTracker = null;
break;

View File

@ -7,20 +7,11 @@ package org.mozilla.gecko.toolbar;
import android.content.Context;
import android.util.AttributeSet;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.tabs.TabCurve;
public class PhoneTabsButton extends ShapedButton {
public PhoneTabsButton(Context context, AttributeSet attrs) {
super(context, attrs);
if (!AppConstants.Versions.preLollipop) {
// The Android N preview has issues rendering our tabs button during animations
// unless we use hardware layers, see bug 1264783. For consistency we should
// try and set this across all devices, however on 4.X devices the background
// isn't drawn when we use hardware layers - hence we need to disable this there.
setLayerType(LAYER_TYPE_HARDWARE, null);
}
}
@Override

View File

@ -975,7 +975,7 @@ var BrowserApp = {
},
_migrateUI: function() {
const UI_VERSION = 2;
const UI_VERSION = 3;
let currentUIVersion = 0;
try {
currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
@ -1040,6 +1040,20 @@ var BrowserApp = {
}
}
if (currentUIVersion < 3) {
const kOldSafeBrowsingPref = "browser.safebrowsing.enabled";
// Default value is set to true, a user pref means that the pref was
// set to false.
if (Services.prefs.prefHasUserValue(kOldSafeBrowsingPref) &&
!Services.prefs.getBoolPref(kOldSafeBrowsingPref)) {
Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled",
false);
// Should just remove support for the pref entirely, even if it's
// only in about:config
Services.prefs.clearUserPref(kOldSafeBrowsingPref);
}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
},
@ -4153,7 +4167,7 @@ Tab.prototype = {
return;
jsonMessage = this.makeFeedMessage(target, type);
} else if (list.indexOf("[search]" != -1) && aEvent.type == "DOMLinkAdded") {
} else if (list.indexOf("[search]") != -1 && aEvent.type == "DOMLinkAdded") {
this.sendOpenSearchMessage(target);
}
if (!jsonMessage)

View File

@ -29,7 +29,7 @@ Migrated from Robocop: https://bugzilla.mozilla.org/show_bug.cgi?id=1184186
BrowserApp._migrateUI();
// Check that migration version increased.
is(Services.prefs.getIntPref("browser.migration.version"), 2, "found expected version");
is(Services.prefs.getIntPref("browser.migration.version"), 3, "found expected version");
// Check that user pref value was reset.
is(Services.prefs.prefHasUserValue("nglayout.debug.paint_flashing"), false, "found expected user value");

View File

@ -5,11 +5,17 @@
package org.mozilla.gecko.tests;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.mozilla.gecko.background.db.CursorDumper;
import org.mozilla.gecko.db.BrowserContract;
import org.mozilla.gecko.db.BrowserContract.UrlAnnotations.SyncStatus;
import org.mozilla.gecko.db.URLMetadata;
import org.mozilla.gecko.db.URLMetadataTable;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@ -188,6 +194,16 @@ public class testBrowserProvider extends ContentProviderTest {
return thumbnailEntry;
}
private ContentValues createUrlMetadataEntry(final String url, final String tileImage, final String tileColor,
final String touchIcon) {
final ContentValues values = new ContentValues();
values.put(URLMetadataTable.URL_COLUMN, url);
values.put(URLMetadataTable.TILE_IMAGE_URL_COLUMN, tileImage);
values.put(URLMetadataTable.TILE_COLOR_COLUMN, tileColor);
values.put(URLMetadataTable.TOUCH_ICON_COLUMN, touchIcon);
return values;
}
private ContentValues createUrlAnnotationEntry(final String url, final String key, final String value,
final long dateCreated) {
final ContentValues values = new ContentValues();
@ -243,6 +259,13 @@ public class testBrowserProvider extends ContentProviderTest {
null);
}
private Cursor getUrlMetadataByUrl(final String url) throws Exception {
return mProvider.query(URLMetadataTable.CONTENT_URI, null,
URLMetadataTable.URL_COLUMN + " = ?",
new String[] { url },
null);
}
@Override
public void setUp() throws Exception {
super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db");
@ -269,6 +292,7 @@ public class testBrowserProvider extends ContentProviderTest {
mTests.add(new TestDeleteHistoryThumbnails());
mTests.add(new TestInsertUrlAnnotations());
mTests.add(new TestInsertUrlMetadata());
mTests.add(new TestBatchOperations());
@ -1492,6 +1516,116 @@ public class testBrowserProvider extends ContentProviderTest {
}
}
private class TestInsertUrlMetadata extends TestCase {
@Override
public void test() throws Exception {
testInsertionViaContentProvider();
testInsertionViaUrlMetadata();
// testRetrievalViaUrlMetadata depends on data added in the previous two tests
testRetrievalViaUrlMetadata();
}
final String url1 = "http://mozilla.org";
final String url2 = "http://hello.org";
private void testInsertionViaContentProvider() throws Exception {
final String tileImage = "http://mozilla.org/tileImage.png";
final String tileColor = "#FF0000";
final String touchIcon = "http://mozilla.org/touchIcon.png";
// We can only use update since the redirection machinery doesn't exist for insert
mProvider.update(URLMetadataTable.CONTENT_URI.buildUpon().appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build(),
createUrlMetadataEntry(url1, tileImage, tileColor, touchIcon),
URLMetadataTable.URL_COLUMN + "=?",
new String[] {url1}
);
final Cursor c = getUrlMetadataByUrl(url1);
try {
mAsserter.is(c.getCount(), 1, "URL metadata inserted via Content Provider not found");
} finally {
c.close();
}
}
private void testInsertionViaUrlMetadata() throws Exception {
final String tileImage = "http://hello.org/tileImage.png";
final String tileColor = "#FF0000";
final String touchIcon = "http://hello.org/touchIcon.png";
final Map<String, Object> data = new HashMap<>();
data.put(URLMetadataTable.URL_COLUMN, url2);
data.put(URLMetadataTable.TILE_IMAGE_URL_COLUMN, tileImage);
data.put(URLMetadataTable.TILE_COLOR_COLUMN, tileColor);
data.put(URLMetadataTable.TOUCH_ICON_COLUMN, touchIcon);
getTestProfile().getDB().getURLMetadata().save(mResolver, data);
final Cursor c = getUrlMetadataByUrl(url2);
try {
mAsserter.is(c.moveToFirst(), true, "URL metadata inserted via UrlMetadata not found");
} finally {
c.close();
}
}
private void testRetrievalViaUrlMetadata() {
// LocalURLMetadata has some caching of results: we need to test that this caching
// doesn't prevent us from accessing data that might not have been loaded into the cache.
// We do this by first doing queries with a subset of data, then later querying additional
// data for a given URL. E.g. even if the first query results in only the requested
// column being cached, the subsequent query should still retrieve all requested columns.
// (In this case the URL may be cached but without all data, we need to make sure that
// this state is correctly handled.)
URLMetadata metadata = getTestProfile().getDB().getURLMetadata();
Map<String, Map<String, Object>> results;
Map<String, Object> urlData;
// 1: retrieve just touch Icons for URL 1
results = metadata.getForURLs(mResolver,
Collections.singletonList(url1),
Collections.singletonList(URLMetadataTable.TOUCH_ICON_COLUMN));
mAsserter.is(results.containsKey(url1), true, "URL 1 not found in results");
urlData = results.get(url1);
mAsserter.is(urlData.containsKey(URLMetadataTable.TOUCH_ICON_COLUMN), true, "touchIcon column missing in UrlMetadata results");
// 2: retrieve just tile color for URL 2
results = metadata.getForURLs(mResolver,
Collections.singletonList(url2),
Collections.singletonList(URLMetadataTable.TILE_COLOR_COLUMN));
mAsserter.is(results.containsKey(url2), true, "URL 2 not found in results");
urlData = results.get(url2);
mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_COLOR_COLUMN), true, "touchIcon column missing in UrlMetadata results");
// 3: retrieve all columns for both URLs
final List<String> urls = Arrays.asList(url1, url2);
results = metadata.getForURLs(mResolver,
urls,
Arrays.asList(URLMetadataTable.TILE_IMAGE_URL_COLUMN,
URLMetadataTable.TILE_COLOR_COLUMN,
URLMetadataTable.TOUCH_ICON_COLUMN
));
mAsserter.is(results.containsKey(url1), true, "URL 1 not found in results");
mAsserter.is(results.containsKey(url2), true, "URL 2 not found in results");
for (final String url : urls) {
urlData = results.get(url);
mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_IMAGE_URL_COLUMN), true, "touchIcon column missing in UrlMetadata results");
mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_COLOR_COLUMN), true, "touchIcon column missing in UrlMetadata results");
mAsserter.is(urlData.containsKey(URLMetadataTable.TOUCH_ICON_COLUMN), true, "touchIcon column missing in UrlMetadata results");
}
}
}
private class TestCombinedView extends TestCase {
@Override
public void test() throws Exception {

View File

@ -2,7 +2,7 @@
--------------------------------------------------------------------------
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2006 Julian R Seward. All
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
@ -36,8 +36,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Julian Seward, Cambridge, UK.
jseward@bzip.org
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
--------------------------------------------------------------------------

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
@ -48,7 +48,7 @@ void BZ2_bz__AssertH__fail ( int errcode )
"component, you should also report this bug to the author(s)\n"
"of that program. Please make an effort to report this bug;\n"
"timely and accurate bug reports eventually lead to higher\n"
"quality software. Thanks. Julian Seward, 15 February 2005.\n\n",
"quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
errcode,
BZ2_bzlibVersion()
);
@ -598,6 +598,7 @@ Bool unRLE_obuf_to_output_FAST ( DState* s )
UInt32 c_tPos = s->tPos;
char* cs_next_out = s->strm->next_out;
unsigned int cs_avail_out = s->strm->avail_out;
Int32 ro_blockSize100k = s->blockSize100k;
/* end restore */
UInt32 avail_out_INIT = cs_avail_out;
@ -1371,23 +1372,7 @@ const char * BZ_API(BZ2_bzlibVersion)(void)
#ifndef BZ_NO_STDIO
/*---------------------------------------------------*/
#ifdef WINCE
#ifndef setmode
#define setmode _setmode
#endif
#ifndef O_BINARY
#define O_BINARY _O_BINARY
#endif
static
FILE * fdopen(int fd, const char *mode)
{
wchar_t wMode[10];
MultiByteToWideChar(CP_ACP, 0, mode, -1, wMode, 10);
return _wfdopen((void*)fd, wMode);
}
#endif
#if (defined(_WIN32) || defined(OS2) || defined(MSDOS))
#if defined(_WIN32) || defined(OS2) || defined(MSDOS)
# include <fcntl.h>
# include <io.h>
# define SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY)

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
@ -36,7 +36,7 @@
/*-- General stuff. --*/
#define BZ_VERSION "1.0.4, 20-Dec-2006"
#define BZ_VERSION "1.0.6, 6-Sept-2010"
typedef char Char;
typedef unsigned char Bool;
@ -442,11 +442,15 @@ typedef
/*-- Macros for decompression. --*/
#define BZ_GET_FAST(cccc) \
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
s->tPos = s->tt[s->tPos]; \
cccc = (UChar)(s->tPos & 0xff); \
s->tPos >>= 8;
#define BZ_GET_FAST_C(cccc) \
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) return True; \
c_tPos = c_tt[c_tPos]; \
cccc = (UChar)(c_tPos & 0xff); \
c_tPos >>= 8;
@ -469,8 +473,10 @@ typedef
(((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
#define BZ_GET_SMALL(cccc) \
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
s->tPos = GET_LL(s->tPos);
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) return True; \
cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \
s->tPos = GET_LL(s->tPos);
/*-- externs for decompression. --*/

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
@ -381,6 +381,13 @@ Int32 BZ2_decompress ( DState* s )
es = -1;
N = 1;
do {
/* Check that N doesn't get too big, so that es doesn't
go negative. The maximum value that can be
RUNA/RUNB encoded is equal to the block size (post
the initial RLE), viz, 900k, so bounding N at 2
million should guard against overflow without
rejecting any legitimate inputs. */
if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR);
if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
if (nextSym == BZ_RUNB) es = es + (1+1) * N;
N = N * 2;
@ -485,15 +492,28 @@ Int32 BZ2_decompress ( DState* s )
RETURN(BZ_DATA_ERROR);
/*-- Set up cftab to facilitate generation of T^(-1) --*/
/* Check: unzftab entries in range. */
for (i = 0; i <= 255; i++) {
if (s->unzftab[i] < 0 || s->unzftab[i] > nblock)
RETURN(BZ_DATA_ERROR);
}
/* Actually generate cftab. */
s->cftab[0] = 0;
for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1];
for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1];
/* Check: cftab entries in range. */
for (i = 0; i <= 256; i++) {
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
/* s->cftab[i] can legitimately be == nblock */
RETURN(BZ_DATA_ERROR);
}
}
/* Check: cftab entries non-descending. */
for (i = 1; i <= 256; i++) {
if (s->cftab[i-1] > s->cftab[i]) {
RETURN(BZ_DATA_ERROR);
}
}
s->state_out_len = 0;
s->state_out_ch = 0;

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -8,8 +8,8 @@
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.

View File

@ -5088,7 +5088,7 @@ pref("urlclassifier.max-complete-age", 2700);
pref("urlclassifier.alternate_error_page", "blocked");
// Enable phishing protection
pref("browser.safebrowsing.enabled", true);
pref("browser.safebrowsing.phishing.enabled", true);
// Enable malware protection
pref("browser.safebrowsing.malware.enabled", true);

View File

@ -37,7 +37,7 @@ class TestSafeBrowsingNotificationBar(FirefoxTestCase):
}
]
self.prefs.set_pref('browser.safebrowsing.enabled', True)
self.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
self.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
# Give the browser a little time, because SafeBrowsing.jsm takes a while

View File

@ -23,7 +23,7 @@ class TestSafeBrowsingWarningPages(FirefoxTestCase):
'https://www.itisatrap.org/firefox/its-an-attack.html'
]
self.prefs.set_pref('browser.safebrowsing.enabled', True)
self.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
self.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
# Give the browser a little time, because SafeBrowsing.jsm takes a

View File

@ -197,7 +197,7 @@ class DesktopInstance(GeckoInstance):
'browser.newtab.url': 'about:newtab',
'browser.newtabpage.enabled': False,
'browser.reader.detectedFirstArticle': True,
'browser.safebrowsing.enabled': False,
'browser.safebrowsing.phishing.enabled': False,
'browser.safebrowsing.forbiddenURIs.enabled': False,
'browser.safebrowsing.malware.enabled': False,
'browser.safebrowsing.blockedURIs.enabled': False,

View File

@ -106,7 +106,7 @@ DEFAULTS = dict(
'http://127.0.0.1/safebrowsing-dummy/update',
'privacy.trackingprotection.introURL':
'http://127.0.0.1/trackingprotection/tour',
'browser.safebrowsing.enabled': False,
'browser.safebrowsing.phishing.enabled': False,
'browser.safebrowsing.malware.enabled': False,
'browser.safebrowsing.forbiddenURIs.enabled': False,
'browser.safebrowsing.blockedURIs.enabled': False,

View File

@ -5151,6 +5151,14 @@
"kind": "count",
"description": "Number of archived Telemetry pings discarded because they exceeded the maximum size"
},
"TELEMETRY_PING_SUBMISSION_WAITING_CLIENTID": {
"alert_emails": ["telemetry-client-dev@mozilla.com"],
"expires_in_version": "never",
"kind": "count",
"releaseChannelCollection": "opt-out",
"bug_numbers": [1233986],
"description": "The number of pings that were submitted and had to wait for a client id (i.e. before it was cached or loaded from disk)"
},
"TELEMETRY_DISCARDED_PENDING_PINGS_SIZE_MB": {
"alert_emails": ["telemetry-client-dev@mozilla.com"],
"expires_in_version": "never",
@ -8949,7 +8957,7 @@
"n_values": 12,
"releaseChannelCollection": "opt-out",
"bug_numbers": [1241294],
"description": "Why e10s is enabled or disabled (0=ENABLED_BY_USER, 1=ENABLED_BY_DEFAULT, 2=DISABLED_BY_USER, 3=DISABLED_IN_SAFE_MODE, 4=DISABLED_FOR_ACCESSIBILITY, 5=DISABLED_FOR_MAC_GFX, 6=DISABLED_FOR_BIDI, 7=DISABLED_FOR_ADDONS)"
"description": "Why e10s is enabled or disabled (0=ENABLED_BY_USER, 1=ENABLED_BY_DEFAULT, 2=DISABLED_BY_USER, 3=DISABLED_IN_SAFE_MODE, 4=DISABLED_FOR_ACCESSIBILITY, 5=DISABLED_FOR_MAC_GFX, 6=DISABLED_FOR_BIDI, 7=DISABLED_FOR_ADDONS, 8=FORCE_DISABLED, 9=DISABLED_FOR_XPLAYERS, 10=DISABLED_FOR_OS_VERSION)"
},
"E10S_WINDOW": {
"expires_in_version": "never",

View File

@ -299,15 +299,6 @@ this.TelemetryController = Object.freeze({
return Impl.savePing(aType, aPayload, aFilePath, options);
},
/**
* The client id send with the telemetry ping.
*
* @return The client id as string, or null.
*/
get clientID() {
return Impl.clientID;
},
/**
* The session recorder instance managed by Telemetry.
* @return {Object} The active SessionRecorder instance or null if not available.
@ -444,8 +435,10 @@ var Impl = {
},
/**
* Submit ping payloads to Telemetry. This will assemble a complete ping, adding
* environment data, client id and some general info.
* Internal function to assemble a complete ping, adding environment data, client id
* and some general info. This waits on the client id to be loaded/generated if it's
* not yet available. Note that this function is synchronous unless we need to load
* the client id.
* Depending on configuration, the ping will be sent to the server (immediately or later)
* and archived locally.
*
@ -459,6 +452,44 @@ var Impl = {
* @param {Object} [aOptions.overrideEnvironment=null] set to override the environment data.
* @returns {Promise} Test-only - a promise that is resolved with the ping id once the ping is stored or sent.
*/
_submitPingLogic: Task.async(function* (aType, aPayload, aOptions) {
// Make sure to have a clientId if we need one. This cover the case of submitting
// a ping early during startup, before Telemetry is initialized, if no client id was
// cached.
if (!this._clientID && aOptions.addClientId) {
Telemetry.getHistogramById("TELEMETRY_PING_SUBMISSION_WAITING_CLIENTID").add();
// We can safely call |getClientID| here and during initialization: we would still
// spawn and return one single loading task.
this._clientID = yield ClientID.getClientID();
}
const pingData = this.assemblePing(aType, aPayload, aOptions);
this._log.trace("submitExternalPing - ping assembled, id: " + pingData.id);
// Always persist the pings if we are allowed to. We should not yield on any of the
// following operations to keep this function synchronous for the majority of the calls.
let archivePromise = TelemetryArchive.promiseArchivePing(pingData)
.catch(e => this._log.error("submitExternalPing - Failed to archive ping " + pingData.id, e));
let p = [ archivePromise ];
p.push(TelemetrySend.submitPing(pingData));
return Promise.all(p).then(() => pingData.id);
}),
/**
* Submit ping payloads to Telemetry.
*
* @param {String} aType The type of the ping.
* @param {Object} aPayload The actual data payload for the ping.
* @param {Object} [aOptions] Options object.
* @param {Boolean} [aOptions.addClientId=false] true if the ping should contain the client
* id, false otherwise.
* @param {Boolean} [aOptions.addEnvironment=false] true if the ping should contain the
* environment data.
* @param {Object} [aOptions.overrideEnvironment=null] set to override the environment data.
* @returns {Promise} Test-only - a promise that is resolved with the ping id once the ping is stored or sent.
*/
submitExternalPing: function send(aType, aPayload, aOptions) {
this._log.trace("submitExternalPing - type: " + aType + ", aOptions: " + JSON.stringify(aOptions));
@ -471,19 +502,9 @@ var Impl = {
return Promise.reject(new Error("Invalid type string submitted."));
}
const pingData = this.assemblePing(aType, aPayload, aOptions);
this._log.trace("submitExternalPing - ping assembled, id: " + pingData.id);
// Always persist the pings if we are allowed to.
let archivePromise = TelemetryArchive.promiseArchivePing(pingData)
.catch(e => this._log.error("submitExternalPing - Failed to archive ping " + pingData.id, e));
let p = [ archivePromise ];
p.push(TelemetrySend.submitPing(pingData));
let promise = Promise.all(p);
let promise = this._submitPingLogic(aType, aPayload, aOptions);
this._trackPendingPingTask(promise);
return promise.then(() => pingData.id);
return promise;
},
/**
@ -814,10 +835,6 @@ var Impl = {
return undefined;
},
get clientID() {
return this._clientID;
},
/**
* Get an object describing the current state of this module for AsyncShutdown diagnostics.
*/

View File

@ -77,7 +77,10 @@ const PingServer = {
promiseNextRequest: function() {
const deferred = this._defers[this._currentDeferred++];
return deferred.promise;
// Send the ping to the consumer on the next tick, so that the completion gets
// signaled to Telemetry.
return new Promise(r => Services.tm.currentThread.dispatch(() => r(deferred.promise),
Ci.nsIThread.DISPATCH_NORMAL));
},
promiseNextPing: function() {

View File

@ -6,6 +6,7 @@
"use strict";
Cu.import("resource://gre/modules/ClientID.jsm", this);
Cu.import("resource://gre/modules/TelemetryController.jsm", this);
Cu.import("resource://gre/modules/TelemetryArchive.jsm", this);
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
@ -402,7 +403,7 @@ add_task(function* test_clientId() {
// Check that a ping submitted after the delayed telemetry initialization completed
// should get a valid client id.
yield TelemetryController.testReset();
const clientId = TelemetryController.clientID;
const clientId = yield ClientID.getClientID();
let id = yield TelemetryController.submitExternalPing("test-type", {}, {addClientId: true});
let ping = yield TelemetryArchive.promiseArchivedPingById(id);

View File

@ -107,14 +107,6 @@ function run_test() {
add_task(function* asyncSetup() {
yield TelemetryController.testSetup();
gClientID = yield ClientID.getClientID();
// We should have cached the client id now. Lets confirm that by
// checking the client id before the async ping setup is finished.
let promisePingSetup = TelemetryController.testReset();
do_check_eq(TelemetryController.clientID, gClientID);
yield promisePingSetup;
});
// Ensure that not overwriting an existing file fails silently
@ -128,6 +120,10 @@ add_task(function* test_overwritePing() {
// Checks that a sent ping is correctly received by a dummy http server.
add_task(function* test_simplePing() {
PingServer.start();
// Update the Telemetry Server preference with the address of the local server.
// Otherwise we might end up sending stuff to a non-existing server after
// |TelemetryController.testReset| is called.
Preferences.set(TelemetryController.Constants.PREF_SERVER, "http://localhost:" + PingServer.port);
yield sendPing(false, false);
let request = yield PingServer.promiseNextRequest();
@ -151,8 +147,6 @@ add_task(function* test_disableDataUpload() {
return;
}
const PREF_TELEMETRY_SERVER = "toolkit.telemetry.server";
// Disable FHR upload: this should trigger a deletion ping.
Preferences.set(PREF_FHR_UPLOAD_ENABLED, false);
@ -190,25 +184,83 @@ add_task(function* test_disableDataUpload() {
PingServer.start();
// We set the new server using the pref, otherwise it would get reset with
// |TelemetryController.testReset|.
Preferences.set(PREF_TELEMETRY_SERVER, "http://localhost:" + PingServer.port);
Preferences.set(TelemetryController.Constants.PREF_SERVER, "http://localhost:" + PingServer.port);
// Reset the controller to spin the ping sending task.
yield TelemetryController.testReset();
ping = yield PingServer.promiseNextPing();
checkPingFormat(ping, DELETION_PING_TYPE, true, false);
// Wait on ping activity to settle before moving on to the next test. If we were
// to shut down telemetry, even though the PingServer caught the expected pings,
// TelemetrySend could still be processing them (clearing pings would happen in
// a couple of ticks). Shutting down would cancel the request and save them as
// pending pings.
yield TelemetrySend.testWaitOnOutgoingPings();
// Restore FHR Upload.
Preferences.set(PREF_FHR_UPLOAD_ENABLED, true);
});
add_task(function* test_pingHasClientId() {
// Send a ping with a clientId.
const PREF_CACHED_CLIENTID = "toolkit.telemetry.cachedClientID";
// Make sure we have no cached client ID for this test: we'll try to send
// a ping with it while Telemetry is being initialized.
Preferences.reset(PREF_CACHED_CLIENTID);
yield TelemetryController.testShutdown();
yield ClientID._reset();
yield TelemetryStorage.testClearPendingPings();
// And also clear the counter histogram since we're here.
let h = Telemetry.getHistogramById("TELEMETRY_PING_SUBMISSION_WAITING_CLIENTID");
h.clear();
// Init telemetry and try to send a ping with a client ID.
let promisePingSetup = TelemetryController.testReset();
yield sendPing(true, false);
Assert.equal(h.snapshot().sum, 1,
"We must have a ping waiting for the clientId early during startup.");
// Wait until we are fully initialized. Pings will be assembled but won't get
// sent before then.
yield promisePingSetup;
let ping = yield PingServer.promiseNextPing();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
// Fetch the client ID after initializing and fetching the the ping, so we
// don't unintentionally trigger its loading. We'll still need the client ID
// to see if the ping looks sane.
gClientID = yield ClientID.getClientID();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
Assert.equal(ping.clientId, gClientID, "The correct clientId must be reported.");
// Shutdown Telemetry so we can safely restart it.
yield TelemetryController.testShutdown();
yield TelemetryStorage.testClearPendingPings();
// We should have cached the client ID now. Lets confirm that by checking it before
// the async ping setup is finished.
h.clear();
promisePingSetup = TelemetryController.testReset();
yield sendPing(true, false);
yield promisePingSetup;
// Check that we received the cached client id.
Assert.equal(h.snapshot().sum, 0, "We must have used the cached clientId.");
ping = yield PingServer.promiseNextPing();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
Assert.equal(ping.clientId, gClientID,
"Telemetry should report the correct cached clientId.");
// Check that sending a ping without relying on the cache, after the
// initialization, still works.
Preferences.reset(PREF_CACHED_CLIENTID);
yield TelemetryController.testShutdown();
yield TelemetryStorage.testClearPendingPings();
yield TelemetryController.testReset();
yield sendPing(true, false);
ping = yield PingServer.promiseNextPing();
checkPingFormat(ping, TEST_PING_TYPE, true, false);
Assert.equal(ping.clientId, gClientID, "The correct clientId must be reported.");
Assert.equal(h.snapshot().sum, 0, "No ping should have been waiting for a clientId.");
});
add_task(function* test_pingHasEnvironment() {

View File

@ -167,7 +167,7 @@ this.SafeBrowsing = {
log("reading prefs");
this.debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.phishing.enabled");
this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
this.trackingEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.enabled") || Services.prefs.getBoolPref("privacy.trackingprotection.pbmode.enabled");
this.forbiddenEnabled = Services.prefs.getBoolPref("browser.safebrowsing.forbiddenURIs.enabled");

View File

@ -63,7 +63,7 @@ LazyLogModule gUrlClassifierDbServiceLog("UrlClassifierDbService");
#define CHECK_MALWARE_PREF "browser.safebrowsing.malware.enabled"
#define CHECK_MALWARE_DEFAULT false
#define CHECK_PHISHING_PREF "browser.safebrowsing.enabled"
#define CHECK_PHISHING_PREF "browser.safebrowsing.phishing.enabled"
#define CHECK_PHISHING_DEFAULT false
#define CHECK_TRACKING_PREF "privacy.trackingprotection.enabled"

View File

@ -74,7 +74,7 @@ SpecialPowers.pushPrefEnv(
{"set" : [["urlclassifier.trackingTable", "test-track-simple"],
["privacy.trackingprotection.enabled", true],
["browser.safebrowsing.malware.enabled", false],
["browser.safebrowsing.enabled", false],
["browser.safebrowsing.phishing.enabled", false],
["channelclassifier.allowlist_example", true]]},
test);
@ -87,7 +87,7 @@ function test() {
aWindow.close();
// Safe Browsing turned ON, tracking protection should still work
SpecialPowers.setBoolPref("browser.safebrowsing.enabled", true);
SpecialPowers.setBoolPref("browser.safebrowsing.phishing.enabled", true);
testOnWindow(function(aWindow) {
checkLoads(aWindow, true);
aWindow.close();

View File

@ -30,7 +30,7 @@ prefBranch.setIntPref("urlclassifier.gethashnoise", 0);
// Enable malware/phishing checking for tests
prefBranch.setBoolPref("browser.safebrowsing.malware.enabled", true);
prefBranch.setBoolPref("browser.safebrowsing.blockedURIs.enabled", true);
prefBranch.setBoolPref("browser.safebrowsing.enabled", true);
prefBranch.setBoolPref("browser.safebrowsing.phishing.enabled", true);
// Enable all completions for tests
prefBranch.setCharPref("urlclassifier.disallow_completions", "");

View File

@ -224,7 +224,7 @@ module.exports = {
addSyntheticLine(`*/`, 0);
}
addSyntheticLine(`var bindings = {`, bindings.textLine);
addSyntheticLine(`this.bindings = {`, bindings.textLine);
for (let binding of bindings.children) {
if (binding.local != "binding" || binding.namespace != NS_XBL) {
@ -263,8 +263,9 @@ module.exports = {
addSyntheticLine(indent(3) + `get ${item.attributes.name}() {`, item.textLine);
// TODO This will probably break some style rules when. We need
// to inject this next to the first non-whitespace character
addSyntheticLine(indent(4) + `return`, item.textLine);
addNodeLines(item, 4);
addSyntheticLine(indent(4) + `return (`, item.textLine);
addNodeLines(item, 5);
addSyntheticLine(indent(4) + `);`, item.textLine);
addSyntheticLine(indent(3) + `},`, item.textEndLine);
break;
}