Bug 845484 - [Metro] Add choices of private data to clear in the options flyout [r=mbrubeck]

This commit is contained in:
Rodrigo Silveira 2013-03-25 11:11:11 -07:00
Родитель 52d0a07575
Коммит 786cf4f461
13 изменённых файлов: 276 добавлений и 42 удалений

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

@ -128,6 +128,7 @@ let ScriptContexts = {};
["TopSitesSnappedView", "chrome://browser/content/TopSites.js"],
["TopSitesStartView", "chrome://browser/content/TopSites.js"],
["Sanitizer", "chrome://browser/content/sanitize.js"],
["SanitizeUI", "chrome://browser/content/sanitizeUI.js"],
["SSLExceptions", "chrome://browser/content/exceptions.js"],
#ifdef MOZ_SERVICES_SYNC
["WeaveGlue", "chrome://browser/content/sync.js"],

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

@ -1024,20 +1024,8 @@ var BrowserUI = {
this.undoCloseTab();
break;
case "cmd_sanitize":
{
let title = Strings.browser.GetStringFromName("clearPrivateData.title");
let message = Strings.browser.GetStringFromName("clearPrivateData.message");
let clear = Services.prompt.confirm(window, title, message);
if (clear) {
// disable the button temporarily to indicate something happened
let button = document.getElementById("prefs-clear-data");
button.disabled = true;
setTimeout(function() { button.disabled = false; }, 5000);
Sanitizer.sanitize();
}
SanitizeUI.onSanitize();
break;
}
case "cmd_flyout_back":
FlyoutPanelsUI.hide();
MetroUtils.showSettingsFlyout();
@ -1444,7 +1432,7 @@ var SyncPanelUI = {
init: function() {
// Run some setup code the first time the panel is shown.
Elements.syncFlyout.addEventListener("PopupChanged", function onShow(aEvent) {
if (aEvent.detail && aEvent.popup === Elements.syncFlyout) {
if (aEvent.detail && aEvent.target === Elements.syncFlyout) {
Elements.syncFlyout.removeEventListener("PopupChanged", onShow, false);
WeaveGlue.init();
}
@ -1677,14 +1665,14 @@ var DialogUI = {
this._hidePopup();
this._popup = { "panel": aPanel,
"elements": (aElements instanceof Array) ? aElements : [aElements] };
this._dispatchPopupChanged(true);
this._dispatchPopupChanged(true, aPanel);
},
popPopup: function popPopup(aPanel) {
if (!this._popup || aPanel != this._popup.panel)
return;
this._popup = null;
this._dispatchPopupChanged(false);
this._dispatchPopupChanged(false, aPanel);
},
_hidePopup: function _hidePopup() {
@ -1710,11 +1698,10 @@ var DialogUI = {
}
},
_dispatchPopupChanged: function _dispatchPopupChanged(aVisible) {
_dispatchPopupChanged: function _dispatchPopupChanged(aVisible, aElement) {
let event = document.createEvent("UIEvents");
event.initUIEvent("PopupChanged", true, true, window, aVisible);
event.popup = this._popup;
Elements.stack.dispatchEvent(event);
aElement.dispatchEvent(event);
},
_isEventInsidePopup: function _isEventInsidePopup(aEvent) {

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

@ -428,10 +428,34 @@
<settings id="prefs-charencoding" label="&optionsHeader.char.title;">
<setting pref="browser.menu.showCharacterEncoding" title="&optionsHeader.char.options.label;" type="bool"/>
</settings>
<settings id="prefs-privdata" label="&optionsHeader.privacy.clearPrivateData.title;">
<setting title="&optionsHeader.privacy.clearPrivateData.label;" type="control">
<button id="prefs-clear-data" label="&optionsHeader.privacy.clearPrivateData.button;" command="cmd_sanitize"/>
</setting>
<settings id="prefs-privdata" label="&clearPrivateData.title;">
<description>&clearPrivateData.label;</description>
<checkbox id="prefs-privdata-history" itemName="history" label="&clearPrivateData.history;" checked="true" />
<checkbox id="prefs-privdata-other" label="&clearPrivateData.otherdata;"/>
<hbox id="prefs-privdata-subitems" >
<checkbox class="privdata-subitem-item" checked="true" itemName="downloads" label="&clearPrivateData.downloadHist;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="formdata" label="&clearPrivateData.formSearchHist;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="cookies" label="&clearPrivateData.cookies;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="passwords" label="&clearPrivateData.passwords;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="cache" label="&clearPrivateData.cache;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="offlineApps" label="&clearPrivateData.offline;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="siteSettings" label="&clearPrivateData.sitePref;"/>
<checkbox class="privdata-subitem-item" checked="true" itemName="sessions" label="&clearPrivateData.logins;"/>
</hbox>
<hbox align="center">
<button id="prefs-clear-data" label="&clearPrivateData.button;" command="cmd_sanitize" flex="1" />
<deck id="clear-notification" flex="2" selectedIndex="0" align="center">
<spacer id="clear-notification-empty"/>
<hbox id="clear-notification-clearing" align="center">
<!-- TODO: we need a more metro-y throbber. See bug 852622 -->
<image src="chrome://browser/skin/images/throbber.png" />
</hbox>
<description id="clear-notification-done">&clearPrivateData.done;</description>
</deck>
</hbox>
</settings>
<setting pref="signon.rememberSignons" title="&optionsHeader.privacy.passwords.label;" type="bool"/>
<settings id="prefs-donottrack" label="&optionsHeader.privacy.doNotTrack.title;">

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

@ -7,8 +7,9 @@ var PreferencesPanelView = {
init: function pv_init() {
// Run some setup code the first time the panel is shown.
Elements.prefsFlyout.addEventListener("PopupChanged", function onShow(aEvent) {
if (aEvent.detail && aEvent.popup === Elements.prefsFlyout) {
if (aEvent.detail && aEvent.target === Elements.prefsFlyout) {
Elements.prefsFlyout.removeEventListener("PopupChanged", onShow, false);
SanitizeUI.init();
}
}, false);
}

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

@ -8,6 +8,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
function Sanitizer() {}
Sanitizer.prototype = {
// warning to the caller: this one may raise an exception (e.g. bug #265028)
clearItem: function (aItemName)
@ -99,22 +100,12 @@ Sanitizer.prototype = {
{
var cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
cookieMgr.removeAll();
},
get canClear()
{
return true;
}
},
geolocation: {
clear: function ()
{
// clear any network geolocation provider sessions
try {
var branch = Services.prefs.getBranch("geo.wifi.access_token.");
branch.deleteBranch("");
branch = Services.prefs.getBranch("geo.request.remember.");
branch.deleteBranch("");
} catch (e) {dump(e);}

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

@ -0,0 +1,86 @@
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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/. */
"use strict";
var SanitizeUI = {
_sanitizer: null,
_privDataElement: null,
get _privData() {
if (this._privDataElement === null) {
this._privDataElement = document.getElementById("prefs-privdata");
}
return this._privDataElement;
},
init: function () {
this._sanitizer = new Sanitizer();
this._privData.addEventListener("CheckboxStateChange", this, true);
},
_clearNotificationTimeout: null,
onSanitize: function onSanitize() {
let button = document.getElementById("prefs-clear-data");
let clearNotificationDeck = document.getElementById("clear-notification");
let clearNotificationEmpty = document.getElementById("clear-notification-empty");
let clearNotificationClearing = document.getElementById("clear-notification-clearing");
let clearNotificationDone = document.getElementById("clear-notification-done");
let allCheckboxes = SanitizeUI._privData.querySelectorAll("checkbox");
let allSelected = SanitizeUI._privData.querySelectorAll(
"#prefs-privdata-history[checked], " +
"#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]");
// disable button and checkboxes temporarily to indicate something is happening
button.disabled = true;
for (let checkbox of allCheckboxes) {
checkbox.disabled = true;
}
clearNotificationDeck.selectedPanel = clearNotificationClearing;
// Run asynchronously to let UI update
setTimeout(function() {
for (let item of allSelected) {
let itemName = item.getAttribute("itemName");
try {
SanitizeUI._sanitizer.clearItem(itemName);
} catch(e) {
Components.utils.reportError("Error sanitizing " + itemName + ": " + e);
}
}
button.disabled = false;
for (let checkbox of allCheckboxes) {
checkbox.disabled = false;
}
clearNotificationDeck.selectedPanel = clearNotificationDone;
// Clear notifications after 4 seconds
clearTimeout(SanitizeUI._clearNotificationTimeout);
SanitizeUI._clearNotificationTimeout = setTimeout(function() {
clearNotificationDeck.selectedPanel = clearNotificationEmpty;
}, 4000);
}, 0);
},
/* Disable the clear button when nothing is selected */
_onCheckboxChange: function _onCheckboxChange() {
let anySelected = SanitizeUI._privData.querySelector(
"#prefs-privdata-history[checked], " +
"#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]");
let clearButton = document.getElementById("prefs-clear-data");
clearButton.disabled = !anySelected;
},
handleEvent: function (aEvent) {
switch (aEvent.type) {
case "CheckboxStateChange":
this._onCheckboxChange();
break;
}
},
};

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

@ -72,6 +72,7 @@ chrome.jar:
content/cursor.css (content/cursor.css)
% content branding %content/branding/
content/sanitize.js (content/sanitize.js)
content/sanitizeUI.js (content/sanitizeUI.js)
content/input.js (content/input.js)
content/Util.js (content/Util.js)
content/bookmarks.js (content/bookmarks.js)

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

@ -25,6 +25,7 @@ BROWSER_TESTS = \
browser_plugin_input_mouse.js \
browser_plugin_input_keyboard.js \
browser_context_menu_tests.js \
browser_sanitize_ui.js \
browser_context_menu_tests_01.html \
browser_context_menu_tests_02.html \
browser_context_menu_tests_03.html \

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

@ -0,0 +1,107 @@
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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/. */
"use strict";
var SanitizeHelper = {
_originalSanitizer: null,
MockSanitizer: {
clearCalled: [],
clearItem: function clearItem(aItemName) {
info("Clear item called for: " + aItemName);
this.clearCalled.push(aItemName);
}
},
setUp: function setUp() {
SanitizeHelper._originalSanitizer = SanitizeUI._sanitizer;
SanitizeUI._sanitizer = SanitizeHelper.MockSanitizer;
},
tearDown: function tearDown() {
SanitizeUI._sanitizer = SanitizeHelper._originalSanitizer;
},
};
function getAllSelected() {
return document.getElementById("prefs-privdata").querySelectorAll(
"#prefs-privdata-history[checked], " +
"#prefs-privdata-other[checked] + #prefs-privdata-subitems .privdata-subitem-item[checked]");
}
gTests.push({
tearDown: SanitizeHelper.tearDown,
desc: "Test sanitizer UI",
run: function testSanitizeUI() {
// Show options flyout
let promise = waitForEvent(Elements.prefsFlyout, "PopupChanged", 2000);
Elements.prefsFlyout.show();
yield promise;
ok(promise && !(promise instanceof Error), "Wait for PopupChanged");
// Make sure it's opened
yield waitForEvent(Elements.prefsFlyout, "transitionend", 1000);
SanitizeHelper.setUp();
// Test initial state
let allSelected = getAllSelected();
// Only history should be selected
ok(allSelected.length === 1 && allSelected[0].getAttribute("itemName") === "history", "History is initially selected.");
let othersCheck = document.getElementById("prefs-privdata-other");
othersCheck.setAttribute("checked", "true");
let othersSubitems = document.getElementById("prefs-privdata-subitems");
yield waitForCondition(function (){
return othersSubitems.style.display !== "none";
}, 500);
allSelected = getAllSelected();
// History and all checkboxes under othersSubitems should be selected
ok(allSelected.length === 1 + othersSubitems.querySelectorAll("checkbox").length,
"All checkboxes are selected.");
// Select only downloads and passwords
let callItems = ["downloads", "passwords"];
for (let checkbox of allSelected) {
if (callItems.indexOf(checkbox.getAttribute("itemName")) === -1) {
checkbox.removeAttribute("checked");
}
}
let clearButton = document.getElementById("prefs-clear-data");
clearButton.doCommand();
let clearNotificationDeck = document.getElementById("clear-notification");
let clearNotificationDone = document.getElementById("clear-notification-done");
// Wait until command is done.
yield waitForCondition(function (){
return clearNotificationDeck.selectedPanel == clearNotificationDone;
}, 1000);
ok(SanitizeHelper.MockSanitizer.clearCalled.length === callItems.length, "All expected items were called");
SanitizeHelper.MockSanitizer.clearCalled.forEach(function(item) {
ok(callItems.indexOf(item) >= 0, "Sanitized " + item);
});
// hide options flyout
promise = waitForEvent(Elements.prefsFlyout, "PopupChanged", 2000);
Elements.prefsFlyout.hide();
yield promise;
ok(promise && !(promise instanceof Error), "Wait for PopupChanged");
}
});
function test() {
runTests();
}

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

@ -88,7 +88,3 @@ tabs.emptyTabTitle=New Tab
# Open Search
# LOCALIZATION NOTE (opensearch.search): %S is the word or phrase typed by the user
opensearch.search=Search: %S
# Clear Private Data
clearPrivateData.title=Clear Private Data
clearPrivateData.message=Delete your browsing history and settings, including passwords and cookies?

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

@ -18,9 +18,22 @@
<!ENTITY optionsHeader.char.title "Character Encoding">
<!ENTITY optionsHeader.char.autodetect.label "Auto-detect">
<!ENTITY optionsHeader.char.options.label "Show encoding options on the App Bar">
<!ENTITY optionsHeader.privacy.clearPrivateData.title "Clear Private Data">
<!ENTITY optionsHeader.privacy.clearPrivateData.label "Clear your browsing history, passwords, cookies, and form data on this device">
<!ENTITY optionsHeader.privacy.clearPrivateData.button "Clear">
<!ENTITY clearPrivateData.title "Clear Private Data">
<!ENTITY clearPrivateData.label "Clear your browsing history, passwords, cookies, and form data on this device">
<!ENTITY clearPrivateData.button "Clear">
<!ENTITY clearPrivateData.done "Done!">
<!ENTITY clearPrivateData.history "Browsing history">
<!ENTITY clearPrivateData.otherdata "Other data (passwords, cache, cookies, etc)">
<!ENTITY clearPrivateData.downloadHist "Download history">
<!ENTITY clearPrivateData.cookies "Cookies">
<!ENTITY clearPrivateData.cache "Cache">
<!ENTITY clearPrivateData.sitePref "Site preferences">
<!ENTITY clearPrivateData.formSearchHist "Form &amp; search history">
<!ENTITY clearPrivateData.passwords "Saved passwords">
<!ENTITY clearPrivateData.offline "Offline website data">
<!ENTITY clearPrivateData.logins "Active logins">
<!ENTITY optionsHeader.privacy.passwords.label "Remember Passwords">
<!ENTITY optionsHeader.privacy.doNotTrack.title "Tracking">
<!ENTITY optionsHeader.privacy.doNotTrack.label "Tell websites not to track me">

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

@ -761,6 +761,31 @@ setting[type="directory"] > .preferences-alignment {
display: none;
}
/* Clear private data prefs */
/* hide subitems when other data checkbox is not checked */
#prefs-privdata-other:not([checked]) + #prefs-privdata-subitems {
display: none;
}
#prefs-privdata-subitems {
display: block;
padding-left: @metro_spacing_xnormal@;
font-size: @metro_font_snormal@;
}
/* arrange sub-items in two columns */
.privdata-subitem-item {
display: inline-block;
vertical-align: middle;
margin: 0;
width: 50%;
}
#clear-notification-done {
font-weight: bold;
}
/* Start UI (Autocomplete + New Tab Page) ----------------------------------- */
#start-container {

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

@ -61,6 +61,7 @@
%define metro_border_thick 2px
%define metro_border_xthick 4px
%define metro_font_snormal 14px
%define metro_font_normal 15px
%define metro_font_large 25px
%define metro_font_xlarge 45px