merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-07-24 12:13:10 +02:00
Родитель 12edfc7c01 3f09481f19
Коммит 95623ac8d4
49 изменённых файлов: 805 добавлений и 267 удалений

Просмотреть файл

@ -53,11 +53,19 @@ let TrackingProtection = {
return Services.telemetry.getHistogramById("TRACKING_PROTECTION_EVENTS");
},
onSecurityChange(state) {
onSecurityChange(state, isSimulated) {
if (!this.enabled) {
return;
}
// Only animate the shield if the event was not fired directly from
// the tabbrowser (due to a browser change).
if (isSimulated) {
this.icon.removeAttribute("animate");
} else {
this.icon.setAttribute("animate", "true");
}
let {
STATE_BLOCKED_TRACKING_CONTENT, STATE_LOADED_TRACKING_CONTENT
} = Ci.nsIWebProgressListener;

Просмотреть файл

@ -4009,7 +4009,7 @@ var XULBrowserWindow = {
init: function () {
// Initialize the security button's state and tooltip text.
var securityUI = gBrowser.securityUI;
this.onSecurityChange(null, null, securityUI.state);
this.onSecurityChange(null, null, securityUI.state, true);
},
setJSStatus: function () {
@ -4357,7 +4357,13 @@ var XULBrowserWindow = {
_state: null,
_lastLocation: null,
onSecurityChange: function (aWebProgress, aRequest, aState) {
// This is called in multiple ways:
// 1. Due to the nsIWebProgressListener.onSecurityChange notification.
// 2. Called by tabbrowser.xml when updating the current browser.
// 3. Called directly during this object's initializations.
// aRequest will be null always in case 2 and 3, and sometimes in case 1 (for
// instance, there won't be a request when STATE_BLOCKED_TRACKING_CONTENT is observed).
onSecurityChange: function (aWebProgress, aRequest, aState, aIsSimulated) {
// Don't need to do anything if the data we use to update the UI hasn't
// changed
let uri = gBrowser.currentURI;
@ -4368,6 +4374,10 @@ var XULBrowserWindow = {
this._state = aState;
this._lastLocation = spec;
if (typeof(aIsSimulated) != "boolean" && typeof(aIsSimulated) != "undefined") {
throw "onSecurityChange: aIsSimulated receieved an unexpected type";
}
// aState is defined as a bitmask that may be extended in the future.
// We filter out any unknown bits before testing for known values.
const wpl = Components.interfaces.nsIWebProgressListener;
@ -4403,7 +4413,7 @@ var XULBrowserWindow = {
uri = Services.uriFixup.createExposableURI(uri);
} catch (e) {}
gIdentityHandler.checkIdentity(this._state, uri);
TrackingProtection.onSecurityChange(this._state);
TrackingProtection.onSecurityChange(this._state, aIsSimulated);
},
// simulate all change notifications after switching tabs

Просмотреть файл

@ -1100,8 +1100,11 @@
false);
if (securityUI) {
// Include the true final argument to indicate that this event is
// simulated (instead of being observed by the webProgressListener).
this._callProgressListeners(null, "onSecurityChange",
[webProgress, null, securityUI.state], true, false);
[webProgress, null, securityUI.state, true],
true, false);
}
var listener = this.mTabListeners[this.tabContainer.selectedIndex] || null;

Просмотреть файл

@ -424,6 +424,8 @@ support-files =
benignPage.html
[browser_trackingUI_3.js]
tags = trackingprotection
[browser_trackingUI_4.js]
tags = trackingprotection
support-files =
trackingPage.html
benignPage.html

Просмотреть файл

@ -1,13 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test that the Tracking Protection section is visible in the Control Center
// and has the correct state for the cases when:
// * A page with no tracking elements is loaded.
// * A page with tracking elements is loaded and they are blocked.
// * A page with tracking elements is loaded and they are not blocked.
// See also Bugs 1175327, 1043801, 1178985
/*
* Test that the Tracking Protection section is visible in the Control Center
* and has the correct state for the cases when:
* 1) A page with no tracking elements is loaded.
* 2) A page with tracking elements is loaded and they are blocked.
* 3) A page with tracking elements is loaded and they are not blocked.
* See also Bugs 1175327, 1043801, 1178985
*/
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const PREF = "privacy.trackingprotection.enabled";
@ -15,12 +13,12 @@ const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
let TrackingProtection = null;
let browser = null;
let tabbrowser = null;
let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
registerCleanupFunction(function() {
TrackingProtection = browser = null;
TrackingProtection = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF);
Services.prefs.clearUserPref(PB_PREF);
@ -30,44 +28,45 @@ registerCleanupFunction(function() {
});
function hidden(sel) {
let win = browser.ownerGlobal;
let win = tabbrowser.ownerGlobal;
let el = win.document.querySelector(sel);
let display = win.getComputedStyle(el).getPropertyValue("display", null);
return display === "none";
let opacity = win.getComputedStyle(el).getPropertyValue("opacity", null);
return display === "none" || opacity === "0";
}
function clickButton(sel) {
let win = browser.ownerGlobal;
let win = tabbrowser.ownerGlobal;
let el = win.document.querySelector(sel);
el.doCommand();
}
function testBenignPage() {
info("Non-tracking content must not be blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
ok (!TrackingProtection.content.hasAttribute("state"), "content: no state");
ok (!TrackingProtection.icon.hasAttribute("state"), "icon: no state");
ok(!TrackingProtection.container.hidden, "The container is visible");
ok(!TrackingProtection.content.hasAttribute("state"), "content: no state");
ok(!TrackingProtection.icon.hasAttribute("state"), "icon: no state");
ok (hidden("#tracking-protection-icon"), "icon is hidden");
ok (hidden("#tracking-action-block"), "blockButton is hidden");
ok (hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(hidden("#tracking-protection-icon"), "icon is hidden");
ok(hidden("#tracking-action-block"), "blockButton is hidden");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
// Make sure that the no tracking elements message appears
ok (!hidden("#tracking-not-detected"), "labelNoTracking is visible");
ok (hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok (hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
ok(!hidden("#tracking-not-detected"), "labelNoTracking is visible");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
}
function testTrackingPage(window) {
info("Tracking content must be blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
is (TrackingProtection.content.getAttribute("state"), "blocked-tracking-content",
ok(!TrackingProtection.container.hidden, "The container is visible");
is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content",
'content: state="blocked-tracking-content"');
is (TrackingProtection.icon.getAttribute("state"), "blocked-tracking-content",
is(TrackingProtection.icon.getAttribute("state"), "blocked-tracking-content",
'icon: state="blocked-tracking-content"');
ok (!hidden("#tracking-protection-icon"), "icon is visible");
ok (hidden("#tracking-action-block"), "blockButton is hidden");
ok(!hidden("#tracking-protection-icon"), "icon is visible");
ok(hidden("#tracking-action-block"), "blockButton is hidden");
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
@ -79,27 +78,27 @@ function testTrackingPage(window) {
}
// Make sure that the blocked tracking elements message appears
ok (hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok (hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok (!hidden("#tracking-blocked"), "labelTrackingBlocked is visible");
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok(hidden("#tracking-loaded"), "labelTrackingLoaded is hidden");
ok(!hidden("#tracking-blocked"), "labelTrackingBlocked is visible");
}
function testTrackingPageUnblocked() {
info("Tracking content must be white-listed and not blocked");
ok (!TrackingProtection.container.hidden, "The container is visible");
is (TrackingProtection.content.getAttribute("state"), "loaded-tracking-content",
ok(!TrackingProtection.container.hidden, "The container is visible");
is(TrackingProtection.content.getAttribute("state"), "loaded-tracking-content",
'content: state="loaded-tracking-content"');
is (TrackingProtection.icon.getAttribute("state"), "loaded-tracking-content",
is(TrackingProtection.icon.getAttribute("state"), "loaded-tracking-content",
'icon: state="loaded-tracking-content"');
ok (!hidden("#tracking-protection-icon"), "icon is visible");
ok (!hidden("#tracking-action-block"), "blockButton is visible");
ok (hidden("#tracking-action-unblock"), "unblockButton is hidden");
ok(!hidden("#tracking-protection-icon"), "icon is visible");
ok(!hidden("#tracking-action-block"), "blockButton is visible");
ok(hidden("#tracking-action-unblock"), "unblockButton is hidden");
// Make sure that the blocked tracking elements message appears
ok (hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok (!hidden("#tracking-loaded"), "labelTrackingLoaded is visible");
ok (hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
ok(hidden("#tracking-not-detected"), "labelNoTracking is hidden");
ok(!hidden("#tracking-loaded"), "labelTrackingLoaded is visible");
ok(hidden("#tracking-blocked"), "labelTrackingBlocked is hidden");
}
function* testTrackingProtectionForTab(tab) {
@ -127,40 +126,40 @@ function* testTrackingProtectionForTab(tab) {
add_task(function* testNormalBrowsing() {
yield UrlClassifierTestUtils.addTestTrackers();
browser = gBrowser;
let tab = browser.selectedTab = browser.addTab();
tabbrowser = gBrowser;
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
ok(TrackingProtection, "TP is attached to the browser window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
"TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionForTab(tab);
Services.prefs.setBoolPref(PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = browser.selectedTab = browser.addTab();
tabbrowser = privateWin.gBrowser;
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the private window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
"TP.enabled is based on the pb pref value");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionForTab(tab);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
privateWin.close();
});

Просмотреть файл

@ -1,10 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test that the Tracking Protection section is never visible in the
// Control Center when the feature is off.
// See also Bugs 1175327, 1043801, 1178985.
/*
* Test that the Tracking Protection section is never visible in the
* Control Center when the feature is off.
* See also Bugs 1175327, 1043801, 1178985.
*/
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const PREF = "privacy.trackingprotection.enabled";
@ -12,12 +10,12 @@ const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
let TrackingProtection = null;
let browser = null;
let tabbrowser = null;
let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
registerCleanupFunction(function() {
TrackingProtection = browser = null;
TrackingProtection = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF);
Services.prefs.clearUserPref(PB_PREF);
@ -29,52 +27,52 @@ registerCleanupFunction(function() {
add_task(function* testNormalBrowsing() {
yield UrlClassifierTestUtils.addTestTrackers();
browser = gBrowser;
let tab = browser.selectedTab = browser.addTab();
tabbrowser = gBrowser;
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PREF),
"TP.enabled is based on the original pref value");
Services.prefs.setBoolPref(PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
info("Load a test page containing tracking elements");
yield promiseTabLoadEvent(tab, TRACKING_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
ok(TrackingProtection.container.hidden, "The container is hidden");
info("Load a test page not containing tracking elements");
yield promiseTabLoadEvent(tab, BENIGN_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
ok(TrackingProtection.container.hidden, "The container is hidden");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
browser = privateWin.gBrowser;
let tab = browser.selectedTab = browser.addTab();
tabbrowser = privateWin.gBrowser;
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the private window");
is (TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
is(TrackingProtection.enabled, Services.prefs.getBoolPref(PB_PREF),
"TP.enabled is based on the pb pref value");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled after setting the pref");
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled after setting the pref");
ok(!TrackingProtection.enabled, "TP is disabled after setting the pref");
info("Load a test page containing tracking elements");
yield promiseTabLoadEvent(tab, TRACKING_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
ok(TrackingProtection.container.hidden, "The container is hidden");
info("Load a test page not containing tracking elements");
yield promiseTabLoadEvent(tab, BENIGN_PAGE);
ok (TrackingProtection.container.hidden, "The container is hidden");
ok(TrackingProtection.container.hidden, "The container is hidden");
privateWin.close();
});

Просмотреть файл

@ -1,17 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Test that the Tracking Protection is correctly enabled / disabled
// in both normal and private windows given all possible states of the prefs:
// privacy.trackingprotection.enabled
// privacy.trackingprotection.pbmode.enabled
// See also Bug 1178985.
/*
* Test that the Tracking Protection is correctly enabled / disabled
* in both normal and private windows given all possible states of the prefs:
* privacy.trackingprotection.enabled
* privacy.trackingprotection.pbmode.enabled
* See also Bug 1178985.
*/
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF);
@ -19,41 +15,38 @@ registerCleanupFunction(function() {
});
add_task(function* testNormalBrowsing() {
let browser = gBrowser;
let TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
let TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
Services.prefs.setBoolPref(PB_PREF, false);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
ok(TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
ok(TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
Services.prefs.setBoolPref(PREF, false);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
ok(!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=true)");
ok(!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=true)");
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
let browser = privateWin.gBrowser;
let TrackingProtection = browser.ownerGlobal.TrackingProtection;
ok (TrackingProtection, "TP is attached to the browser window");
let TrackingProtection = privateWin.gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
Services.prefs.setBoolPref(PB_PREF, false);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
ok(TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
ok(TrackingProtection.enabled, "TP is enabled (ENABLED=true,PB=true)");
Services.prefs.setBoolPref(PREF, false);
Services.prefs.setBoolPref(PB_PREF, false);
ok (!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
ok(!TrackingProtection.enabled, "TP is disabled (ENABLED=false,PB=false)");
Services.prefs.setBoolPref(PB_PREF, true);
ok (TrackingProtection.enabled, "TP is enabled (ENABLED=false,PB=true)");
ok(TrackingProtection.enabled, "TP is enabled (ENABLED=false,PB=true)");
privateWin.close();
});

Просмотреть файл

@ -0,0 +1,109 @@
/*
* Test that the Tracking Protection icon is properly animated in the identity
* block when loading tabs and switching between tabs.
* See also Bug 1175858.
*/
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
const PREF = "privacy.trackingprotection.enabled";
const PB_PREF = "privacy.trackingprotection.pbmode.enabled";
const BENIGN_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/benignPage.html";
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/general/trackingPage.html";
let TrackingProtection = null;
let tabbrowser = null;
let {UrlClassifierTestUtils} = Cu.import("resource://testing-common/UrlClassifierTestUtils.jsm", {});
registerCleanupFunction(function() {
TrackingProtection = tabbrowser = null;
UrlClassifierTestUtils.cleanupTestTrackers();
Services.prefs.clearUserPref(PREF);
Services.prefs.clearUserPref(PB_PREF);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
function waitForSecurityChange(numChanges = 1) {
return new Promise(resolve => {
let n = 0;
let listener = {
onSecurityChange: function() {
n = n + 1;
info ("Recieved onSecurityChange event " + n + " of " + numChanges);
if (n >= numChanges) {
tabbrowser.removeProgressListener(listener);
resolve();
}
}
};
tabbrowser.addProgressListener(listener);
});
}
function* testTrackingProtectionAnimation() {
info("Load a test page not containing tracking elements");
let benignTab = yield BrowserTestUtils.openNewForegroundTab(tabbrowser, BENIGN_PAGE);
ok(!TrackingProtection.icon.hasAttribute("state"), "icon: no state");
ok(TrackingProtection.icon.hasAttribute("animate"), "icon: animate");
info("Load a test page containing tracking elements");
let trackingTab = yield BrowserTestUtils.openNewForegroundTab(tabbrowser, TRACKING_PAGE);
ok(TrackingProtection.icon.hasAttribute("state"), "icon: state");
ok(TrackingProtection.icon.hasAttribute("animate"), "icon: animate");
info("Switch from tracking -> benign tab");
let securityChanged = waitForSecurityChange();
tabbrowser.selectedTab = benignTab;
yield securityChanged;
ok(!TrackingProtection.icon.hasAttribute("state"), "icon: no state");
ok(!TrackingProtection.icon.hasAttribute("animate"), "icon: no animate");
info("Switch from benign -> tracking tab");
securityChanged = waitForSecurityChange();
tabbrowser.selectedTab = trackingTab;
yield securityChanged;
ok(TrackingProtection.icon.hasAttribute("state"), "icon: state");
ok(!TrackingProtection.icon.hasAttribute("animate"), "icon: no animate");
info("Reload tracking tab");
securityChanged = waitForSecurityChange(2);
tabbrowser.reload();
yield securityChanged;
ok(TrackingProtection.icon.hasAttribute("state"), "icon: state");
ok(TrackingProtection.icon.hasAttribute("animate"), "icon: animate");
}
add_task(function* testNormalBrowsing() {
yield UrlClassifierTestUtils.addTestTrackers();
tabbrowser = gBrowser;
TrackingProtection = gBrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the browser window");
Services.prefs.setBoolPref(PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionAnimation();
});
add_task(function* testPrivateBrowsing() {
let privateWin = yield promiseOpenAndLoadWindow({private: true}, true);
tabbrowser = privateWin.gBrowser;
TrackingProtection = tabbrowser.ownerGlobal.TrackingProtection;
ok(TrackingProtection, "TP is attached to the private window");
Services.prefs.setBoolPref(PB_PREF, true);
ok(TrackingProtection.enabled, "TP is enabled after setting the pref");
yield testTrackingProtectionAnimation();
privateWin.close();
});

Просмотреть файл

@ -89,8 +89,8 @@
<vbox>
<hbox align="center">
<checkbox id="privacyDoNotTrackCheckbox"
label="&dntTrackingNotOkay2.label;"
accesskey="&dntTrackingNotOkay2.accesskey;"
label="&dntTrackingNotOkay3.label;"
accesskey="&dntTrackingNotOkay3.accesskey;"
preference="privacy.donottrackheader.enabled"/>
<label id="doNotTrackInfo"
class="text-link"
@ -103,8 +103,8 @@
<hbox align="center">
<checkbox id="trackingProtection"
preference="privacy.trackingprotection.enabled"
accesskey="&trackingProtection2.accesskey;"
label="&trackingProtection2.label;" />
accesskey="&trackingProtection3.accesskey;"
label="&trackingProtection3.label;" />
<label id="trackingProtectionLearnMore"
class="text-link"
value="&trackingProtectionLearnMore.label;"/>
@ -114,8 +114,8 @@
<hbox align="center">
<checkbox id="trackingProtectionPBM"
preference="privacy.trackingprotection.pbmode.enabled"
accesskey="&trackingProtectionPBM2.accesskey;"
label="&trackingProtectionPBM2.label;" />
accesskey="&trackingProtectionPBM3.accesskey;"
label="&trackingProtectionPBM3.label;" />
<label id="trackingProtectionPBMLearnMore"
class="text-link"
value="&trackingProtectionPBMLearnMore.label;"/>

Просмотреть файл

@ -96,8 +96,8 @@
<hbox align="center">
<checkbox id="trackingProtection"
preference="privacy.trackingprotection.enabled"
accesskey="&trackingProtection2.accesskey;"
label="&trackingProtection2.label;" />
accesskey="&trackingProtection3.accesskey;"
label="&trackingProtection3.label;" />
<image id="trackingProtectionImage"
src="chrome://browser/skin/bad-content-blocked-16.png"/>
</hbox>
@ -111,8 +111,8 @@
<vbox>
<hbox align="center">
<checkbox id="privacyDoNotTrackCheckbox"
label="&dntTrackingNotOkay2.label;"
accesskey="&dntTrackingNotOkay2.accesskey;"
label="&dntTrackingNotOkay3.label;"
accesskey="&dntTrackingNotOkay3.accesskey;"
preference="privacy.donottrackheader.enabled"/>
</hbox>
<hbox align="center"

Просмотреть файл

@ -44,6 +44,10 @@ exports.getHighlighterUtils = function(toolbox) {
// Is the highlighter currently in pick mode
let isPicking = false;
// Is the box model already displayed, used to prevent dispatching
// unnecessary requests, especially during toolbox shutdown
let isNodeFrontHighlighted = false;
/**
* Release this utils, nullifying the references to the toolbox
*/
@ -203,6 +207,7 @@ exports.getHighlighterUtils = function(toolbox) {
return;
}
isNodeFrontHighlighted = true;
if (isRemoteHighlightable()) {
yield toolbox.highlighter.showBoxModel(nodeFront, options);
} else {
@ -256,7 +261,8 @@ exports.getHighlighterUtils = function(toolbox) {
// Note that if isRemoteHighlightable is true, there's no need to hide the
// highlighter as the walker uses setTimeout to hide it after some time
if (forceHide && toolbox.highlighter && isRemoteHighlightable()) {
if (isNodeFrontHighlighted && forceHide && toolbox.highlighter && isRemoteHighlightable()) {
isNodeFrontHighlighted = false;
yield toolbox.highlighter.hideBoxModel();
}

Просмотреть файл

@ -12,7 +12,7 @@
const TEST_URL = "data:text/html;charset=utf8,<div>test element</div>";
add_task(function*() {
let {inspector} = yield addTab(TEST_URL).then(openInspector);
let {toolbox, inspector} = yield addTab(TEST_URL).then(openInspector);
info("Select the test node with the browser ctx menu");
yield selectWithBrowserMenu(inspector);
@ -20,8 +20,10 @@ add_task(function*() {
info("Press arrowUp to focus <body> " +
"(which works if the node was focused properly)");
let onNodeHighlighted = toolbox.once("node-highlight");
EventUtils.synthesizeKey("VK_UP", {});
yield waitForChildrenUpdated(inspector);
yield onNodeHighlighted;
assertNodeSelected(inspector, "body");
info("Select the test node with the element picker");
@ -30,8 +32,10 @@ add_task(function*() {
info("Press arrowUp to focus <body> " +
"(which works if the node was focused properly)");
onNodeHighlighted = toolbox.once("node-highlight");
EventUtils.synthesizeKey("VK_UP", {});
yield waitForChildrenUpdated(inspector);
yield onNodeHighlighted;
assertNodeSelected(inspector, "body");
});

Просмотреть файл

@ -2744,6 +2744,9 @@ RuleEditor.prototype = {
let {ruleProps, isMatching} = response;
if (!ruleProps) {
// Notify for changes, even when nothing changes,
// just to allow tests being able to track end of this request.
ruleView.emit("ruleview-invalid-selector");
return;
}

Просмотреть файл

@ -36,7 +36,9 @@ function* testEditSelector(view, name) {
info("Entering a new selector name and committing");
editor.input.value = name;
let onRuleViewChanged = once(view, "ruleview-invalid-selector");
EventUtils.synthesizeKey("VK_RETURN", {});
yield onRuleViewChanged;
is(view._elementStyle.rules.length, 2, "Should have 2 rules.");
is(getRuleViewRule(view, name), undefined,

Просмотреть файл

@ -4,14 +4,14 @@
<!ENTITY tracking.label "Tracking">
<!ENTITY dntTrackingNotOkay2.label "Tell sites that I do not want to be tracked.">
<!ENTITY dntTrackingNotOkay2.accesskey "n">
<!ENTITY dntTrackingNotOkay3.label "Request that sites not track you.">
<!ENTITY dntTrackingNotOkay3.accesskey "n">
<!ENTITY doNotTrackInfo.label "Learn More">
<!ENTITY trackingProtection2.label "Prevent sites from tracking me.">
<!ENTITY trackingProtection2.accesskey "m">
<!ENTITY trackingProtection3.label "Stop sites from tracking you.">
<!ENTITY trackingProtection3.accesskey "m">
<!ENTITY trackingProtectionLearnMore.label "Learn more">
<!ENTITY trackingProtectionPBM2.label "Prevent sites from tracking my online activity in Private Windows.">
<!ENTITY trackingProtectionPBM2.accesskey "y">
<!ENTITY trackingProtectionPBM3.label "Stop sites from tracking you in Private Windows.">
<!ENTITY trackingProtectionPBM3.accesskey "y">
<!ENTITY trackingProtectionPBMLearnMore.label "Learn more">
<!ENTITY history.label "History">

Просмотреть файл

@ -614,7 +614,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
}
#nav-bar #PanelUI-menu-button {
-moz-padding-start: 7px;
-moz-padding-start: 5px;
-moz-padding-end: 5px;
}

Просмотреть файл

@ -724,7 +724,7 @@ toolbar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-ic
margin-bottom: 0;
padding-top: 1px;
padding-bottom: 1px;
-moz-margin-start: 9px;
-moz-margin-start: 7px;
-moz-margin-end: 7px;
}

Просмотреть файл

@ -21,12 +21,6 @@
%include ../browser.inc
:root {
--panel-ui-button-background-image: linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, transparent),
linear-gradient(to bottom, transparent, hsla(210,54%,20%,.3) 30%, hsla(210,54%,20%,.3) 70%, transparent),
linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, transparent);
--panel-ui-button-background-size: 1px calc(100% - 1px), 1px calc(100% - 1px), 1px calc(100% - 1px) !important;
--panel-ui-button-background-position: 0px 0px, 1px 0px, 2px 0px;
--panel-ui-button-background-repeat: no-repeat;
--panel-ui-exit-subview-gutter-width: 38px;
}
@ -97,14 +91,14 @@
}
#PanelUI-button {
background-image: var(--panel-ui-button-background-image);
background-size: var(--panel-ui-button-background-size);
background-position: var(--panel-ui-button-background-position);
background-repeat: var(--panel-ui-button-background-repeat);
margin-inline-start: 2px;
border-inline-start: 1px solid;
border-image: linear-gradient(transparent, rgba(0,0,0,.1) 20%, rgba(0,0,0,.1) 80%, transparent);
border-image-slice: 1;
}
#PanelUI-button:-moz-locale-dir(rtl) {
background-position: 100% 0, calc(100% - 1px) 0, calc(100% - 2px) 0;
#nav-bar[brighttext] > #PanelUI-button {
border-image-source: linear-gradient(transparent, rgba(100%,100%,100%,.2) 20%, rgba(100%,100%,100%,.2) 80%, transparent);
}
#PanelUI-menu-button[update-status="succeeded"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {

Просмотреть файл

@ -10,8 +10,6 @@
--tab-toolbar-navbar-overlap: 0px;
--space-above-tabbar: 0px;
--toolbarbutton-text-shadow: none;
--panel-ui-button-background-size: 1px calc(100% - 1px);
--panel-ui-button-background-position: 1px 0px;
}
:root[devtoolstheme="dark"] {
@ -60,9 +58,6 @@
--urlbar-dropmarker-2x-region: rect(0px, 11px, 14px, 0px);
--urlbar-dropmarker-active-2x-region: rect(0px, 22px, 14px, 11px);
--search-button-image: url("chrome://browser/skin/devedition/search.svg#search-icon-inverted");
/* Menu button separator */
--panel-ui-button-background-image: linear-gradient(to bottom, transparent, #5F6670 30%, #5F6670 70%, transparent);
}
:root[devtoolstheme="dark"] #identity-box {
@ -115,9 +110,6 @@
/* Url and search bars */
--search-button-image: url("chrome://browser/skin/devedition/search.svg#search-icon");
/* Menu button separator */
--panel-ui-button-background-image: linear-gradient(to bottom, transparent, rgba(0,0,0,0.1) 30%, rgba(0,0,0,0.1) 70%, transparent);
}
/* Give some space to drag the window around while customizing

Просмотреть файл

@ -27,6 +27,7 @@
font-size: .9em;
padding: 2px 5px;
margin-inline-end: 4px;
overflow: hidden;
}
#identity-box:hover,
@ -89,14 +90,24 @@
height: 16px;
margin-inline-end: 2px;
list-style-image: url(chrome://browser/skin/tracking-protection-16.svg);
margin-left: 0;
opacity: 1;
}
#tracking-protection-icon[state="loaded-tracking-content"] {
list-style-image: url(chrome://browser/skin/tracking-protection-disabled-16.svg);
}
#tracking-protection-icon[animate] {
transition: margin-left 200ms ease-out;
}
#tracking-protection-icon:not([state]) {
display: none;
margin-left: -16px;
pointer-events: none;
opacity: 0;
/* Only animate the shield in, when it disappears hide it immediately. */
transition: none;
}
/* MAIN IDENTITY ICON */

Просмотреть файл

@ -195,6 +195,14 @@ treecol {
-moz-margin-end: 8px !important;
}
/* Privacy pane */
#doNotTrackInfo,
#trackingProtectionPBMLearnMore,
#trackingProtectionLearnMore {
margin-top: 0;
}
/* Collapse the non-active vboxes in decks to use only the height the
active vbox needs */
#historyPane:not([selectedIndex="1"]) > #historyDontRememberPane,

Просмотреть файл

@ -655,7 +655,7 @@ toolbar[brighttext] .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
}
#nav-bar #PanelUI-menu-button {
-moz-padding-start: 7px;
-moz-padding-start: 5px;
-moz-padding-end: 5px;
}

Просмотреть файл

@ -67,7 +67,7 @@ tools:: $(ANDROID_APK_NAME).apk
# out of sync with base's build config.
jars_dir := $(DEPTH)/mobile/android/base
stumbler_jars_dir := $(DEPTH)/mobile/android/stumbler
JAVA_BOOTCLASSPATH := $(JAVA_BOOTCLASSPATH):$(subst $(NULL) ,:,$(wildcard $(jars_dir)/*.jar)):$(subst $(NULL) ,:,$(wildcard $(stumbler_jars_dir)/*.jar)):$(ANDROID_COMPAT_LIB)
JAVA_BOOTCLASSPATH := $(JAVA_BOOTCLASSPATH):$(subst $(NULL) ,:,$(wildcard $(jars_dir)/*.jar)):$(subst $(NULL) ,:,$(wildcard $(stumbler_jars_dir)/*.jar)):$(ANDROID_COMPAT_LIB):$(ANDROID_RECYCLERVIEW_LIB)
# We also want to re-compile classes.dex when the associated base
# content changes.
classes.dex: $(wildcard $(jars_dir)/*.jar)

Просмотреть файл

@ -2932,10 +2932,10 @@ nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
if (currentValue != aValue) {
if (aValue) {
TimelineConsumers::AddConsumer(this, mObserved);
TimelineConsumers::AddConsumer(this);
UseEntryScriptProfiling();
} else {
TimelineConsumers::RemoveConsumer(this, mObserved);
TimelineConsumers::RemoveConsumer(this);
UnuseEntryScriptProfiling();
}
}
@ -3092,23 +3092,6 @@ nsDocShell::Now(DOMHighResTimeStamp* aWhen)
return NS_OK;
}
void
nsDocShell::AddProfileTimelineMarker(const char* aName,
TracingMetadata aMetaData)
{
if (IsObserved()) {
mObserved->AddMarker(aName, aMetaData);
}
}
void
nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>&& aMarker)
{
if (IsObserved()) {
mObserved->AddMarker(Move(aMarker));
}
}
NS_IMETHODIMP
nsDocShell::SetWindowDraggingAllowed(bool aValue)
{
@ -13984,7 +13967,7 @@ nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
MakeUnique<JavascriptTimelineMarker>(this, "Javascript", aReason,
aFunctionName, aFilename,
aLineNumber);
AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(this, Move(marker));
}
mJSRunToCompletionDepth++;
}
@ -13997,7 +13980,7 @@ nsDocShell::NotifyJSRunToCompletionStop()
// If last stop, mark interval end.
mJSRunToCompletionDepth--;
if (timelineOn && mJSRunToCompletionDepth == 0) {
AddProfileTimelineMarker("Javascript", TRACING_INTERVAL_END);
TimelineConsumers::AddMarkerForDocShell(this, "Javascript", TRACING_INTERVAL_END);
}
}

Просмотреть файл

@ -258,17 +258,23 @@ public:
// is no longer applied
void NotifyAsyncPanZoomStopped();
// Add new profile timeline markers to this docShell. This will only add
// markers if the docShell is currently recording profile timeline markers.
// See nsIDocShell::recordProfileTimelineMarkers
void AddProfileTimelineMarker(const char* aName, TracingMetadata aMetaData);
void AddProfileTimelineMarker(mozilla::UniquePtr<TimelineMarker>&& aMarker);
private:
// An observed docshell wrapper is created when recording markers is enabled.
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
bool IsObserved() const { return !!mObserved; }
// It is necessary to allow adding a timeline marker wherever a docshell
// instance is available. This operation happens frequently and needs to
// be very fast, so instead of using a Map or having to search for some
// docshell-specific markers storage, a pointer to an `ObservedDocShell` is
// is stored on docshells directly.
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell* aDocShell);
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell* aDocShell, UniquePtr<TimelineMarker>&& aMarker);
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
nsDocShell* aDocShell, const char* aName, TracingMetadata aMetaData);
public:
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
static void CopyFavicon(nsIURI* aOldURI,

Просмотреть файл

@ -8,15 +8,12 @@
#include "mozilla/TimelineConsumers.h"
#include "MainThreadUtils.h"
#include "nsDocShell.h"
namespace mozilla {
AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mName(aName)
, mDocShells()
, mDocShellsRetrieved(false)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
@ -25,31 +22,16 @@ AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
return;
}
mDocShellsRetrieved = TimelineConsumers::GetKnownDocShells(mDocShells);
if (!mDocShellsRetrieved) {
// If we don't successfully populate our vector with *all* docshells being
// observed, don't add markers to *any* of them.
return;
}
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
TimelineConsumers::AddMarkerToAllObservedDocShells(mName, TRACING_INTERVAL_START);
}
AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
{
if (!mDocShellsRetrieved) {
if (TimelineConsumers::IsEmpty()) {
return;
}
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
TimelineConsumers::AddMarkerToAllObservedDocShells(mName, TRACING_INTERVAL_END);
}
} // namespace mozilla

Просмотреть файл

@ -8,7 +8,6 @@
#define mozilla_AutoGlobalTimelineMarker_h_
#include "mozilla/GuardObjects.h"
#include "mozilla/Vector.h"
#include "nsRefPtr.h"
class nsDocShell;
@ -37,12 +36,6 @@ class MOZ_STACK_CLASS AutoGlobalTimelineMarker
// The name of the marker we are adding.
const char* mName;
// The set of docshells that will get the marker.
Vector<nsRefPtr<nsDocShell>> mDocShells;
// True as long as no operation has failed, eg due to OOM.
bool mDocShellsRetrieved;
public:
explicit AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/AutoTimelineMarker.h"
#include "mozilla/TimelineConsumers.h"
#include "MainThreadUtils.h"
#include "nsDocShell.h"
@ -19,25 +20,21 @@ AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
if (TimelineConsumers::IsEmpty()) {
if (!aDocShell || TimelineConsumers::IsEmpty()) {
return;
}
bool isRecordingEnabledForDocShell = false;
nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
aDocShell->GetRecordProfileTimelineMarkers(&isRecordingEnabledForDocShell);
if (isRecordingEnabledForDocShell) {
mDocShell = docShell;
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
mDocShell = static_cast<nsDocShell*>(aDocShell);
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_START);
}
AutoTimelineMarker::~AutoTimelineMarker()
{
if (mDocShell) {
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
if (!mDocShell || TimelineConsumers::IsEmpty()) {
return;
}
TimelineConsumers::AddMarkerForDocShell(mDocShell, mName, TRACING_INTERVAL_END);
}
} // namespace mozilla

Просмотреть файл

@ -21,24 +21,26 @@ TimelineConsumers::GetOrCreateObservedDocShellsList()
}
void
TimelineConsumers::AddConsumer(nsDocShell* aDocShell,
UniquePtr<ObservedDocShell>& aObservedPtr)
TimelineConsumers::AddConsumer(nsDocShell* aDocShell)
{
MOZ_ASSERT(!aObservedPtr);
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(!observed);
sActiveConsumers++;
aObservedPtr.reset(new ObservedDocShell(aDocShell));
GetOrCreateObservedDocShellsList().insertFront(aObservedPtr.get());
observed.reset(new ObservedDocShell(aDocShell));
GetOrCreateObservedDocShellsList().insertFront(observed.get());
}
void
TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell,
UniquePtr<ObservedDocShell>& aObservedPtr)
TimelineConsumers::RemoveConsumer(nsDocShell* aDocShell)
{
MOZ_ASSERT(aObservedPtr);
UniquePtr<ObservedDocShell>& observed = aDocShell->mObserved;
MOZ_ASSERT(observed);
sActiveConsumers--;
aObservedPtr.get()->ClearMarkers();
aObservedPtr.get()->remove();
aObservedPtr.reset(nullptr);
observed.get()->ClearMarkers();
observed.get()->remove();
observed.reset(nullptr);
}
bool
@ -63,4 +65,46 @@ TimelineConsumers::GetKnownDocShells(Vector<nsRefPtr<nsDocShell>>& aStore)
return true;
}
void
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
UniquePtr<TimelineMarker>&& aMarker)
{
if (aDocShell->IsObserved()) {
aDocShell->mObserved->AddMarker(Move(aMarker));
}
}
void
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName, TracingMetadata aMetaData)
{
if (aDocShell->IsObserved()) {
aDocShell->mObserved->AddMarker(aName, aMetaData);
}
}
void
TimelineConsumers::AddMarkerToDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
const char* aName, TracingMetadata aMetaData)
{
for (Vector<nsRefPtr<nsDocShell>>::Range range = aDocShells.all();
!range.empty();
range.popFront()) {
AddMarkerForDocShell(range.front(), aName, aMetaData);
}
}
void
TimelineConsumers::AddMarkerToAllObservedDocShells(const char* aName, TracingMetadata aMetaData)
{
Vector<nsRefPtr<nsDocShell>> docShells;
if (!GetKnownDocShells(docShells)) {
// If we don't successfully populate our vector with *all* docshells being
// observed, don't add the marker to *any* of them.
return;
}
AddMarkerToDocShellsList(docShells, aName, aMetaData);
}
} // namespace mozilla

Просмотреть файл

@ -7,8 +7,9 @@
#ifndef mozilla_TimelineConsumers_h_
#define mozilla_TimelineConsumers_h_
#include "mozilla/LinkedList.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Vector.h"
#include "timeline/ObservedDocShell.h"
class nsDocShell;
@ -24,12 +25,21 @@ private:
static LinkedList<ObservedDocShell>& GetOrCreateObservedDocShellsList();
public:
static void AddConsumer(nsDocShell* aDocShell,
UniquePtr<ObservedDocShell>& aObservedPtr);
static void RemoveConsumer(nsDocShell* aDocShell,
UniquePtr<ObservedDocShell>& aObservedPtr);
static void AddConsumer(nsDocShell* aDocShell);
static void RemoveConsumer(nsDocShell* aDocShell);
static bool IsEmpty();
static bool GetKnownDocShells(Vector<nsRefPtr<nsDocShell>>& aStore);
// Methods for adding markers to appropriate docshells. These will only add
// markers if the docshell is currently being observed by a timeline.
// See nsIDocShell::recordProfileTimelineMarkers
static void AddMarkerForDocShell(nsDocShell* aDocShell,
UniquePtr<TimelineMarker>&& aMarker);
static void AddMarkerForDocShell(nsDocShell* aDocShell,
const char* aName, TracingMetadata aMetaData);
static void AddMarkerToDocShellsList(Vector<nsRefPtr<nsDocShell>>& aDocShells,
const char* aName, TracingMetadata aMetaData);
static void AddMarkerToAllObservedDocShells(const char* aName, TracingMetadata aMetaData);
};
} // namespace mozilla

Просмотреть файл

@ -1144,7 +1144,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<TimestampTimelineMarker>(docShell, TRACING_TIMESTAMP, key);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
// For `console.time(foo)` and `console.timeEnd(foo)`
else if (isTimelineRecording && aData.Length() == 1) {
@ -1157,7 +1157,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
MakeUnique<ConsoleTimelineMarker>(docShell,
aMethodName == MethodTime ? TRACING_INTERVAL_START : TRACING_INTERVAL_END,
key);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
}
}

Просмотреть файл

@ -1140,7 +1140,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<EventTimelineMarker>(ds, TRACING_INTERVAL_START,
phase, typeStr);
ds->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(ds, Move(marker));
}
}
@ -1151,7 +1151,7 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
if (isTimelineRecording) {
nsDocShell* ds = static_cast<nsDocShell*>(docShell.get());
ds->AddProfileTimelineMarker("DOMEvent", TRACING_INTERVAL_END);
TimelineConsumers::AddMarkerForDocShell(ds, "DOMEvent", TRACING_INTERVAL_END);
}
}
}

Просмотреть файл

@ -247,6 +247,11 @@ IsTypeInList(nsCString &aMimeType, nsCString aTypeList)
commaSeparated += aMimeType;
commaSeparated.Append(',');
// Lower-case the search string and MIME type to properly handle a mixed-case
// type, as MIME types are case insensitive.
ToLowerCase(searchStr);
ToLowerCase(commaSeparated);
return FindInReadable(commaSeparated, start, end);
}

Просмотреть файл

@ -0,0 +1,140 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
Components.utils.import("resource://gre/modules/Services.jsm");
function run_test() {
const pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
const pluginDefaultState = Services.prefs.getIntPref("plugin.default.state");
function reload_plugins_with_allowed_types(allowed_types) {
if (typeof allowed_types === "undefined") {
// If we didn't get an allowed_types string, then unset the pref,
// so the caller can test the behavior when the pref isn't set.
Services.prefs.clearUserPref("plugin.allowed_types");
} else {
Services.prefs.setCharPref("plugin.allowed_types", allowed_types);
}
pluginHost.reloadPlugins();
}
function get_status_for_type(type) {
try {
return pluginHost.getStateForType(type);
} catch(ex) {
// If the type is not allowed, then nsIPluginHost.getStateForType throws
// NS_ERROR_NOT_AVAILABLE, for which we return undefined to make it easier
// to write assertions about the API.
if (ex.result === Cr.NS_ERROR_NOT_AVAILABLE) {
return undefined;
}
throw ex;
}
}
// If allowed_types isn't set, then all plugin types are enabled.
reload_plugins_with_allowed_types();
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
// If allowed_types is set to the empty string, then all plugin types are enabled.
reload_plugins_with_allowed_types("");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
// If allowed_types is set to anything other than the empty string,
// then only types that exactly match its comma-separated entries are enabled,
// so a single space disables all types.
reload_plugins_with_allowed_types(" ");
do_check_eq(get_status_for_type("application/x-test"), undefined);
do_check_eq(get_status_for_type("application/x-Second-Test"), undefined);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
// The rest of the assertions test various values of allowed_types to ensure
// that the correct types are enabled.
reload_plugins_with_allowed_types("application/x-test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), undefined);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-Second-Test");
do_check_eq(get_status_for_type("application/x-test"), undefined);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-nonexistent");
do_check_eq(get_status_for_type("application/x-test"), undefined);
do_check_eq(get_status_for_type("application/x-Second-Test"), undefined);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-test,application/x-Second-Test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-Second-Test,application/x-test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-test,application/x-nonexistent");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), undefined);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-nonexistent,application/x-test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), undefined);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-test,application/x-Second-Test,application/x-nonexistent");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-test,application/x-nonexistent,application/x-Second-Test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-Second-Test,application/x-test,application/x-nonexistent");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-Second-Test,application/x-nonexistent,application/x-test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-nonexistent,application/x-test,application/x-Second-Test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
reload_plugins_with_allowed_types("application/x-nonexistent,application/x-Second-Test,application/x-test");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-Second-Test"), pluginDefaultState);
do_check_eq(get_status_for_type("application/x-nonexistent"), undefined);
// Plugin types are case-insensitive, so matching should be too.
reload_plugins_with_allowed_types("APPLICATION/X-TEST");
do_check_eq(get_status_for_type("application/x-test"), pluginDefaultState);
reload_plugins_with_allowed_types("application/x-test");
do_check_eq(get_status_for_type("APPLICATION/X-TEST"), pluginDefaultState);
// Types must match exactly, so supersets should not enable subset types.
reload_plugins_with_allowed_types("application/x-test-superset");
do_check_eq(get_status_for_type("application/x-test"), undefined);
reload_plugins_with_allowed_types("superset-application/x-test");
do_check_eq(get_status_for_type("application/x-test"), undefined);
// Clean up.
Services.prefs.clearUserPref("plugin.allowed_types");
Services.prefs.clearUserPref("plugin.importedState");
}

Просмотреть файл

@ -3,6 +3,9 @@ skip-if = buildapp == 'mulet' || toolkit == 'android' || toolkit == 'gonk'
head = head_plugins.js
tail =
[test_allowed_types.js]
skip-if = appname == "thunderbird"
reason = plugins are disabled by default in Thunderbird
[test_bug455213.js]
# Bug 676953: test fails consistently on Android
fail-if = os == "android"

Просмотреть файл

@ -3083,7 +3083,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
data->mLayer->SetEventRegions(EventRegions());
}
}
if (!layer) {
// We couldn't optimize to an image layer or a color layer above.
layer = data->mLayer;
@ -5668,7 +5668,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
if (isRecording) {
mozilla::UniquePtr<TimelineMarker> marker =
MakeUnique<LayerTimelineMarker>(docShell, aRegionToDraw);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
}

Просмотреть файл

@ -358,7 +358,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_START,
data->mRestyleHint);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
#if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
@ -375,7 +375,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_END,
data->mRestyleHint);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
}
@ -422,7 +422,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_START,
currentRestyle->mRestyleHint);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
ProcessOneRestyle(currentRestyle->mElement,
@ -434,7 +434,7 @@ RestyleTracker::DoProcessRestyles()
MakeUnique<RestyleTimelineMarker>(docShell,
TRACING_INTERVAL_END,
currentRestyle->mRestyleHint);
docShell->AddProfileTimelineMarker(Move(marker));
TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
}
}
}

Просмотреть файл

@ -8957,7 +8957,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
nsDocShell* docShell = static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
if (docShell) {
docShell->AddProfileTimelineMarker("Reflow", TRACING_INTERVAL_START);
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_START);
}
if (mReflowContinueTimer) {
@ -9134,7 +9134,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
}
if (docShell) {
docShell->AddProfileTimelineMarker("Reflow", TRACING_INTERVAL_END);
TimelineConsumers::AddMarkerForDocShell(docShell, "Reflow", TRACING_INTERVAL_END);
}
return !interrupted;
}

Просмотреть файл

@ -1812,7 +1812,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
for (nsDocShell* docShell : profilingDocShells) {
// For the sake of the profile timeline's simplicity, this is flagged as
// paint even if it includes creating display lists
docShell->AddProfileTimelineMarker("Paint", TRACING_INTERVAL_START);
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_START);
}
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
@ -1829,7 +1829,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
}
#endif
for (nsDocShell* docShell : profilingDocShells) {
docShell->AddProfileTimelineMarker("Paint", TRACING_INTERVAL_END);
TimelineConsumers::AddMarkerForDocShell(docShell, "Paint", TRACING_INTERVAL_END);
}
if (nsContentUtils::XPConnect()) {

Просмотреть файл

@ -45,7 +45,13 @@ let Logins = {
_getLogins: function() {
let logins;
let contentBody = document.getElementById("content-body");
let emptyBody = document.getElementById("empty-body");
let filterIcon = document.getElementById("filter-button");
this._toggleListBody(true);
emptyBody.classList.add("hidden");
try {
logins = Services.logins.getAllLogins();
} catch(e) {
@ -54,20 +60,32 @@ let Logins = {
logins = [];
}
this._toggleListBody(false);
if (!logins.length) {
emptyBody.classList.remove("hidden");
filterIcon.classList.add("hidden");
contentBody.classList.add("hidden");
} else {
emptyBody.classList.add("hidden");
filterIcon.classList.remove("hidden");
}
logins.sort((a, b) => a.hostname.localeCompare(b.hostname));
return this._logins = logins;
},
_toggleListBody: function(isLoading) {
let nonemptyBody = document.getElementById("logins-list-nonempty-body");
let contentBody = document.getElementById("content-body");
let loadingBody = document.getElementById("logins-list-loading-body");
if (isLoading) {
nonemptyBody.classList.add("hidden");
contentBody.classList.add("hidden");
loadingBody.classList.remove("hidden");
} else {
loadingBody.classList.add("hidden");
nonemptyBody.classList.remove("hidden");
contentBody.classList.remove("hidden");
}
},

Просмотреть файл

@ -29,7 +29,7 @@
<li id="filter-button"></li>
</ul>
</div>
<div id="logins-list-nonempty-body">
<div id="content-body">
<div id="logins-list" class="list"/>
<div id="filter-input-container" hidden="true">
<input id="filter-input" type="search"/>
@ -41,6 +41,13 @@
<object type="image/svg+xml" id="spinner" data="chrome://browser/skin/images/spinning_throbber.svg"/>
</div>
</div>
<div id="empty-body" class="hidden">
<div id="empty-obj-text-container">
<object type="image/svg+xml" id="empty-icon" data="chrome://browser/skin/images/icon_key_emptypage.svg"/>
<div class="empty-text">&aboutLogins.emptyLoginText;</div>
<div class="empty-hint">&aboutLogins.emptyLoginHint;</div>
</div>
</div>
</div>
<div id="edit-login-page" class="hidden">
@ -59,7 +66,7 @@
<button id="password-btn"></button>
</div>
<div class="edit-login-div">
<button id="save-btn">&aboutLogins.save;</button>
<button id="save-btn">&aboutLogins.update;</button>
</div>
</div>

Просмотреть файл

@ -424,6 +424,11 @@
@BINPATH@/components/ActivityWrapper.js
@BINPATH@/components/ActivityMessageConfigurator.js
@BINPATH@/components/SystemMessageInternal.js
@BINPATH@/components/SystemMessageManager.js
@BINPATH@/components/SystemMessageCache.js
@BINPATH@/components/SystemMessageManager.manifest
@BINPATH@/components/TCPSocket.js
@BINPATH@/components/TCPSocketParentIntermediary.js
@BINPATH@/components/TCPServerSocket.js

Просмотреть файл

@ -1,6 +1,10 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY % brandDTD
SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY aboutLogins.title "Logins">
<!ENTITY aboutLogins.save "Save">
<!ENTITY aboutLogins.update "Update">
<!ENTITY aboutLogins.emptyLoginText "Keep your logins safe">
<!ENTITY aboutLogins.emptyLoginHint "Logins and credentials you save using &brandShortName; will show up here.">

Просмотреть файл

@ -14,7 +14,7 @@ loginsDialog.confirm=OK
loginsDialog.cancel=Cancel
editLogin.fallbackTitle=Edit Login
editLogin.saved=Saved your changes
editLogin.saved=Saved login
editLogin.couldNotSave=Changes could not be saved
loginsDetails.age=Age: %S days

Просмотреть файл

@ -196,3 +196,32 @@ body {
height: 60px;
width: 60px;
}
#empty-body {
padding-left: 60px;
padding-right: 60px;
}
#empty-obj-text-container {
display: flex;
flex-flow: column;
align-items: center;
text-align: center;
justify-content: center;
}
.empty-text {
color: #363B40;
font-size: 25px;
margin-bottom: 20px;
}
.empty-hint {
color: #777777;
font-size: 20px;
}
#empty-icon {
margin-top: 60px;
margin-bottom: 20px;
}

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="60px" height="60px" viewBox="0 0 180 180" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>Key</title>
<g sketch:type="MSArtboardGroup" fill="#bfbfbf">
<path d="M72,60.75 C72,60.75 59.625,72 59.625,72 C57.375,74.25 58.5,76.5 59.625,77.625 L65.25,82.125 C66.375,83.25 67.5,84.375 65.25,86.625 L0,157.5 L0,176.625 C0,178.875 1.125,180 3.375,180 L33.75,180 C34.875,180 36,178.875 36,177.75 L36,168.75 L48.375,167.625 L47.25,156.375 L55.125,156.375 C55.125,156.375 56.25,156.375 56.25,155.25 L56.25,148.5 L65.25,148.5 L65.25,132.75 L78.75,132.75 L94.5,115.875 C96.75,113.625 99,113.625 101.25,115.875 L106.875,121.5 C109.125,123.75 111.375,123.75 113.625,121.5 L122.625,109.125 C157.125,108.963211 180,82.6329431 180,55.125 C179.4,24.0802676 155.4,0 124.875,0 C95.4,0 68.025,26.3302676 72,60.75 Z M139,54 C131.85,54 126,48.15 126,41 C126,33.85 131.85,28 139,28 C146.15,28 152,33.85 152,41 C152,48.15 146.15,54 139,54 L139,54 Z" sketch:type="MSShapeGroup"></path>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Просмотреть файл

@ -127,3 +127,4 @@ chrome.jar:
skin/images/icon_heart_mdpi.png (images/icon_heart_mdpi.png)
skin/images/icon_heart_xhdpi.png (images/icon_heart_xhdpi.png)
skin/images/icon_heart_xxhdpi.png (images/icon_heart_xxhdpi.png)
skin/images/icon_key_emptypage.svg (images/icon_key_emptypage.svg)

Просмотреть файл

@ -22,6 +22,7 @@ LoginRec.prototype = {
Utils.deferGetSet(LoginRec, "cleartext", [
"hostname", "formSubmitURL",
"httpRealm", "username", "password", "usernameField", "passwordField",
"timeCreated", "timePasswordChanged",
]);
@ -98,6 +99,13 @@ function PasswordStore(name, engine) {
PasswordStore.prototype = {
__proto__: Store.prototype,
_newPropertyBag: function () {
return Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
},
/**
* Return an instance of nsILoginInfo (and, implicitly, nsILoginMetaInfo).
*/
_nsLoginInfoFromRecord: function (record) {
function nullUndefined(x) {
return (x == undefined) ? null : x;
@ -118,13 +126,21 @@ PasswordStore.prototype = {
record.password,
record.usernameField,
record.passwordField);
info.QueryInterface(Ci.nsILoginMetaInfo);
info.guid = record.id;
if (record.timeCreated) {
info.timeCreated = record.timeCreated;
}
if (record.timePasswordChanged) {
info.timePasswordChanged = record.timePasswordChanged;
}
return info;
},
_getLoginFromGUID: function (id) {
let prop = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
let prop = this._newPropertyBag();
prop.setPropertyAsAUTF8String("guid", id);
let logins = Services.logins.searchLogins({}, prop);
@ -169,8 +185,7 @@ PasswordStore.prototype = {
return;
}
let prop = Cc["@mozilla.org/hash-property-bag;1"]
.createInstance(Ci.nsIWritablePropertyBag2);
let prop = this._newPropertyBag();
prop.setPropertyAsAUTF8String("guid", newID);
Services.logins.modifyLogin(oldLogin, prop);
@ -197,6 +212,11 @@ PasswordStore.prototype = {
record.usernameField = login.usernameField;
record.passwordField = login.passwordField;
// Optional fields.
login.QueryInterface(Ci.nsILoginMetaInfo);
record.timeCreated = login.timeCreated;
record.timePasswordChanged = login.timePasswordChanged;
return record;
},

Просмотреть файл

@ -5,6 +5,137 @@ Cu.import("resource://services-sync/engines/passwords.js");
Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js");
function checkRecord(name, record, expectedCount, timeCreated,
expectedTimeCreated, timePasswordChanged,
expectedTimePasswordChanged, recordIsUpdated) {
let engine = Service.engineManager.get("passwords");
let store = engine._store;
let count = {};
let logins = Services.logins.findLogins(count, record.hostname,
record.formSubmitURL, null);
_("Record" + name + ":" + JSON.stringify(logins));
_("Count" + name + ":" + count.value);
do_check_eq(count.value, expectedCount);
if (expectedCount > 0) {
do_check_true(!!store.getAllIDs()[record.id]);
let stored_record = logins[0].QueryInterface(Ci.nsILoginMetaInfo);
if (timeCreated !== undefined) {
do_check_eq(stored_record.timeCreated, expectedTimeCreated);
}
if (timePasswordChanged !== undefined) {
if (recordIsUpdated) {
do_check_true(stored_record.timePasswordChanged >= expectedTimePasswordChanged);
} else {
do_check_eq(stored_record.timePasswordChanged, expectedTimePasswordChanged);
}
return stored_record.timePasswordChanged;
}
} else {
do_check_true(!store.getAllIDs()[record.id]);
}
}
function changePassword(name, hostname, password, expectedCount, timeCreated,
expectedTimeCreated, timePasswordChanged,
expectedTimePasswordChanged, insert, recordIsUpdated) {
const BOGUS_GUID = "zzzzzz" + hostname;
let record = {id: BOGUS_GUID,
hostname: hostname,
formSubmitURL: hostname,
username: "john",
password: password,
usernameField: "username",
passwordField: "password"};
if (timeCreated !== undefined) {
record.timeCreated = timeCreated;
}
if (timePasswordChanged !== undefined) {
record.timePasswordChanged = timePasswordChanged;
}
let engine = Service.engineManager.get("passwords");
let store = engine._store;
if (insert) {
do_check_eq(store.applyIncomingBatch([record]).length, 0);
}
return checkRecord(name, record, expectedCount, timeCreated,
expectedTimeCreated, timePasswordChanged,
expectedTimePasswordChanged, recordIsUpdated);
}
function test_apply_records_with_times(hostname, timeCreated, timePasswordChanged) {
// The following record is going to be inserted in the store and it needs
// to be found there. Then its timestamps are going to be compared to
// the expected values.
changePassword(" ", hostname, "password", 1, timeCreated, timeCreated,
timePasswordChanged, timePasswordChanged, true);
}
function test_apply_multiple_records_with_times() {
// The following records are going to be inserted in the store and they need
// to be found there. Then their timestamps are going to be compared to
// the expected values.
changePassword("A", "http://foo.a.com", "password", 1, undefined, undefined,
undefined, undefined, true);
changePassword("B", "http://foo.b.com", "password", 1, 1000, 1000, undefined,
undefined, true);
changePassword("C", "http://foo.c.com", "password", 1, undefined, undefined,
1000, 1000, true);
changePassword("D", "http://foo.d.com", "password", 1, 1000, 1000, 1000,
1000, true);
// The following records are not going to be inserted in the store and they
// are not going to be found there.
changePassword("NotInStoreA", "http://foo.aaaa.com", "password", 0,
undefined, undefined, undefined, undefined, false);
changePassword("NotInStoreB", "http://foo.bbbb.com", "password", 0, 1000,
1000, undefined, undefined, false);
changePassword("NotInStoreC", "http://foo.cccc.com", "password", 0,
undefined, undefined, 1000, 1000, false);
changePassword("NotInStoreD", "http://foo.dddd.com", "password", 0, 1000,
1000, 1000, 1000, false);
}
function test_apply_same_record_with_different_times() {
// The following record is going to be inserted multiple times in the store
// and it needs to be found there. Then its timestamps are going to be
// compared to the expected values.
var timePasswordChanged = 100;
timePasswordChanged = changePassword("A", "http://a.tn", "password", 1, 100,
100, 100, timePasswordChanged, true);
timePasswordChanged = changePassword("A", "http://a.tn", "password", 1, 100,
100, 800, timePasswordChanged, true,
true);
timePasswordChanged = changePassword("A", "http://a.tn", "password", 1, 500,
100, 800, timePasswordChanged, true,
true);
timePasswordChanged = changePassword("A", "http://a.tn", "password2", 1, 500,
100, 1536213005222, timePasswordChanged,
true, true);
timePasswordChanged = changePassword("A", "http://a.tn", "password2", 1, 500,
100, 800, timePasswordChanged, true, true);
}
function run_test() {
initTestLogging("Trace");
Log.repository.getLogger("Sync.Engine.Passwords").level = Log.Level.Trace;
@ -30,12 +161,9 @@ function run_test() {
let engine = Service.engineManager.get("passwords");
let store = engine._store;
function applyEnsureNoFailures(records) {
do_check_eq(store.applyIncomingBatch(records).length, 0);
}
try {
applyEnsureNoFailures([recordA, recordB]);
do_check_eq(store.applyIncomingBatch([recordA, recordB]).length, 0);
// Only the good record makes it to Services.logins.
let badCount = {};
@ -55,7 +183,17 @@ function run_test() {
do_check_true(!!store.getAllIDs()[BOGUS_GUID_B]);
do_check_true(!store.getAllIDs()[BOGUS_GUID_A]);
test_apply_records_with_times("http://afoo.baz.com", undefined, undefined);
test_apply_records_with_times("http://bfoo.baz.com", 1000, undefined);
test_apply_records_with_times("http://cfoo.baz.com", undefined, 2000);
test_apply_records_with_times("http://dfoo.baz.com", 1000, 2000);
test_apply_multiple_records_with_times();
test_apply_same_record_with_different_times();
} finally {
store.wipe();
}
}
}