mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 06:45:33 +00:00
merge fx-team into m-c
This commit is contained in:
commit
5f352a3725
@ -1343,6 +1343,10 @@ pref("browser.uiCustomization.debug", false);
|
||||
// be fetched. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.uri", "https://accounts.firefox.com/?service=sync&context=fx_desktop_v1");
|
||||
|
||||
// The URL where remote content that forces re-authentication for Firefox Accounts
|
||||
// should be fetched. Must use HTTPS.
|
||||
pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v1");
|
||||
|
||||
// The URL we take the user to when they opt to "manage" their Firefox Account.
|
||||
// Note that this will always need to be in the same TLD as the
|
||||
// "identity.fxaccounts.remote.uri" pref.
|
||||
|
@ -58,10 +58,10 @@ function sha256(str) {
|
||||
function promptForRelink(acctName) {
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
|
||||
let continueLabel = sb.GetStringFromName("continue.label");
|
||||
let title = sb.GetStringFromName("relink.verify.title");
|
||||
let description = sb.formatStringFromName("relink.verify.description",
|
||||
let title = sb.GetStringFromName("relinkVerify.title");
|
||||
let description = sb.formatStringFromName("relinkVerify.description",
|
||||
[acctName], 1);
|
||||
let body = sb.GetStringFromName("relink.verify.heading") +
|
||||
let body = sb.GetStringFromName("relinkVerify.heading") +
|
||||
"\n\n" + description;
|
||||
let ps = Services.prompt;
|
||||
let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
|
||||
@ -76,7 +76,7 @@ function promptForRelink(acctName) {
|
||||
let wrapper = {
|
||||
iframe: null,
|
||||
|
||||
init: function () {
|
||||
init: function (url=null) {
|
||||
let weave = Cc["@mozilla.org/weave/service;1"]
|
||||
.getService(Ci.nsISupports)
|
||||
.wrappedJSObject;
|
||||
@ -92,7 +92,7 @@ let wrapper = {
|
||||
iframe.addEventListener("load", this);
|
||||
|
||||
try {
|
||||
iframe.src = fxAccounts.getAccountsURI();
|
||||
iframe.src = url || fxAccounts.getAccountsURI();
|
||||
} catch (e) {
|
||||
error("Couldn't init Firefox Account wrapper: " + e.message);
|
||||
}
|
||||
@ -236,11 +236,14 @@ function openPrefs() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
let signinQuery = window.location.href.match(/signin=true$/);
|
||||
|
||||
if (signinQuery) {
|
||||
if (window.location.href.contains("action=signin")) {
|
||||
show("remote");
|
||||
wrapper.init();
|
||||
} else if (window.location.href.contains("action=reauth")) {
|
||||
fxAccounts.promiseAccountsForceSigninURI().then(url => {
|
||||
show("remote");
|
||||
wrapper.init(url);
|
||||
});
|
||||
} else {
|
||||
// Check if we have a local account
|
||||
fxAccounts.getSignedInUser().then(user => {
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&aboutAccounts.pageTitle;</title>
|
||||
<title>&syncBrand.fullName.label;</title>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
|
||||
|
||||
@ -39,23 +39,23 @@
|
||||
|
||||
<div id="manage">
|
||||
<header>
|
||||
<h1>&syncBrand.fxa-plural.label;</h1>
|
||||
|
||||
<h2>&syncBrand.shortName.label;</h2>
|
||||
<h1><span>&syncBrand.fullName.label;</span></h1>
|
||||
<h2><span>&aboutAccounts.welcome;</span></h2>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<div class="graphic graphic-sync-intro"> </div>
|
||||
|
||||
<div class="button-row">
|
||||
<a class="button" href="#" onclick="openPrefs()">Manage</a>
|
||||
<a class="button" href="#" onclick="openPrefs()">&aboutAccountsConfig.manage.label;</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div id="intro">
|
||||
<header>
|
||||
<h1>&aboutAccounts.pageTitle;</h1>
|
||||
<h1><span>&syncBrand.fullName.label;</span></h1>
|
||||
<h2><span>&aboutAccounts.welcome;</span></h2>
|
||||
</header>
|
||||
|
||||
<section>
|
||||
|
@ -4,9 +4,7 @@
|
||||
font-weight: 400;
|
||||
src: local('Fira Sans'),
|
||||
local('FiraSans'),
|
||||
url('fonts/firasans-regular.woff') format('woff'),
|
||||
/*url('/fonts/latin/firasans-regular.ttf') format('truetype'),*/
|
||||
/*url('/fonts/latin/firasans-regular.svg#Fira Sans') format('svg');*/
|
||||
url('fonts/firasans-regular.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Fira Sans';
|
||||
@ -14,9 +12,7 @@
|
||||
font-weight: 300;
|
||||
src: local('Fira Sans Light'),
|
||||
local('FiraSansLight'),
|
||||
url('fonts/firasans-light.woff') format('woff'),
|
||||
/*url('/fonts/latin/firasans-light.ttf') format('truetype'),*/
|
||||
/*url('/fonts/latin/firasans-light.svg#Fira Sans') format('svg');*/
|
||||
url('fonts/firasans-light.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Clear Sans';
|
||||
@ -24,8 +20,6 @@
|
||||
font-weight: 400;
|
||||
src: local('Clear Sans'),
|
||||
local('ClearSans'),
|
||||
url('fonts/clearsans-regular.woff') format('woff'),
|
||||
/*url('/fonts/latin/clearsans-regular.ttf') format('truetype'),*/
|
||||
/*url('/fonts/latin/clearsans-regular.svg#Clear Sans') format('svg');*/
|
||||
url('fonts/clearsans-regular.woff') format('woff');
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,6 @@ let CustomizationHandler = {
|
||||
if (gURLBar) {
|
||||
URLBarSetURI();
|
||||
XULBrowserWindow.asyncUpdateUI();
|
||||
BookmarkingUI.updateStarState();
|
||||
}
|
||||
|
||||
// Re-enable parts of the UI we disabled during the dialog
|
||||
|
@ -186,11 +186,11 @@ let gFxAccounts = {
|
||||
});
|
||||
},
|
||||
|
||||
toggle: function (event) {
|
||||
onMenuPanelCommand: function (event) {
|
||||
if (event.originalTarget.hasAttribute("signedin")) {
|
||||
this.openPreferences();
|
||||
} else {
|
||||
this.openSignInPage();
|
||||
this.openAccountsPage();
|
||||
}
|
||||
|
||||
PanelUI.hide();
|
||||
@ -200,7 +200,12 @@ let gFxAccounts = {
|
||||
openPreferences("paneSync");
|
||||
},
|
||||
|
||||
openSignInPage: function () {
|
||||
openAccountsPage: function () {
|
||||
switchToTabHavingURI("about:accounts", true);
|
||||
},
|
||||
|
||||
openSignInAgainPage: function () {
|
||||
// FIXME: This should actually show the pre-filled username version of about:accounts?
|
||||
switchToTabHavingURI("about:accounts?signin=true", true);
|
||||
}
|
||||
};
|
||||
|
@ -362,7 +362,7 @@
|
||||
openInTabs="children"
|
||||
oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
|
||||
onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
|
||||
onpopupshowing="PlacesCommandHook.updateBookmarkAllTabsCommand();
|
||||
onpopupshowing="BookmarkingUI.onMainMenuPopupShowing(event);
|
||||
if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
|
||||
tooltip="bhTooltip" popupsinherittooltip="true">
|
||||
@ -372,8 +372,8 @@
|
||||
key="manBookmarkKb"/>
|
||||
<menuseparator id="organizeBookmarksSeparator"/>
|
||||
<menuitem id="menu_bookmarkThisPage"
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
command="Browser:AddBookmarkAs"
|
||||
observes="bookmarkThisPageBroadcaster"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="subscribeToPageMenuitem"
|
||||
#ifndef XP_MACOSX
|
||||
|
@ -959,39 +959,48 @@ let PlacesToolbarHelper = {
|
||||
|
||||
let BookmarkingUI = {
|
||||
get button() {
|
||||
delete this.button;
|
||||
let widgetGroup = CustomizableUI.getWidget("bookmarks-menu-button");
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_TOOLBAR) {
|
||||
return widgetGroup.forWindow(window).node;
|
||||
}
|
||||
return null;
|
||||
return this.button = widgetGroup.forWindow(window).node;
|
||||
},
|
||||
|
||||
/* Can't make this a self-deleting getter because it's anonymous content
|
||||
* and might lose/regain bindings at some point. */
|
||||
get star() {
|
||||
let button = this.button;
|
||||
return button && document.getAnonymousElementByAttribute(button, "anonid",
|
||||
"button");
|
||||
return document.getAnonymousElementByAttribute(this.button, "anonid",
|
||||
"button");
|
||||
},
|
||||
|
||||
get anchor() {
|
||||
if (!this._shouldUpdateStarState()) {
|
||||
return null;
|
||||
}
|
||||
let widget = CustomizableUI.getWidget("bookmarks-menu-button")
|
||||
.forWindow(window);
|
||||
if (widget.overflowed)
|
||||
return widget.anchor;
|
||||
|
||||
let star = this.star;
|
||||
return star && document.getAnonymousElementByAttribute(star, "class",
|
||||
"toolbarbutton-icon");
|
||||
return document.getAnonymousElementByAttribute(this.star, "class",
|
||||
"toolbarbutton-icon");
|
||||
},
|
||||
|
||||
get broadcaster() {
|
||||
delete this.broadcaster;
|
||||
let broadcaster = document.getElementById("bookmarkThisPageBroadcaster");
|
||||
return this.broadcaster = broadcaster;
|
||||
},
|
||||
|
||||
STATUS_UPDATING: -1,
|
||||
STATUS_UNSTARRED: 0,
|
||||
STATUS_STARRED: 1,
|
||||
get status() {
|
||||
if (!this._shouldUpdateStarState()) {
|
||||
return this.STATUS_UNSTARRED;
|
||||
}
|
||||
if (this._pendingStmt)
|
||||
return this.STATUS_UPDATING;
|
||||
let button = this.button;
|
||||
return button && button.hasAttribute("starred") ? this.STATUS_STARRED
|
||||
: this.STATUS_UNSTARRED;
|
||||
return this.button.hasAttribute("starred") ? this.STATUS_STARRED
|
||||
: this.STATUS_UNSTARRED;
|
||||
},
|
||||
|
||||
get _starredTooltip()
|
||||
@ -1008,6 +1017,15 @@ let BookmarkingUI = {
|
||||
gNavigatorBundle.getString("starButtonOff.tooltip");
|
||||
},
|
||||
|
||||
/**
|
||||
* The type of the area in which the button is currently located.
|
||||
* When in the panel, we don't update the button's icon.
|
||||
*/
|
||||
_currentAreaType: null,
|
||||
_shouldUpdateStarState: function() {
|
||||
return this._currentAreaType == CustomizableUI.TYPE_TOOLBAR;
|
||||
},
|
||||
|
||||
/**
|
||||
* The popup contents must be updated when the user customizes the UI, or
|
||||
* changes the personal toolbar collapsed status. In such a case, any needed
|
||||
@ -1069,7 +1087,7 @@ let BookmarkingUI = {
|
||||
* Handles star styling based on page proxy state changes.
|
||||
*/
|
||||
onPageProxyStateChanged: function BUI_onPageProxyStateChanged(aState) {
|
||||
if (!this.star) {
|
||||
if (!this._shouldUpdateStarState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1080,26 +1098,31 @@ let BookmarkingUI = {
|
||||
}
|
||||
else {
|
||||
this.star.removeAttribute("disabled");
|
||||
this._updateStar();
|
||||
}
|
||||
this._updateToolbarStyle();
|
||||
},
|
||||
|
||||
_updateToolbarStyle: function BUI__updateToolbarStyle() {
|
||||
let button = this.button;
|
||||
if (!button)
|
||||
return;
|
||||
_updateCustomizationState: function BUI__updateCustomizationState() {
|
||||
let placement = CustomizableUI.getPlacementOfWidget("bookmarks-menu-button");
|
||||
this._currentAreaType = placement && CustomizableUI.getAreaType(placement.area);
|
||||
},
|
||||
|
||||
let personalToolbar = document.getElementById("PersonalToolbar");
|
||||
let onPersonalToolbar = button.parentNode == personalToolbar ||
|
||||
button.parentNode.parentNode == personalToolbar;
|
||||
_updateToolbarStyle: function BUI__updateToolbarStyle() {
|
||||
let onPersonalToolbar = false;
|
||||
if (this._currentAreaType == CustomizableUI.TYPE_TOOLBAR) {
|
||||
let personalToolbar = document.getElementById("PersonalToolbar");
|
||||
onPersonalToolbar = this.button.parentNode == personalToolbar ||
|
||||
this.button.parentNode.parentNode == personalToolbar;
|
||||
}
|
||||
|
||||
if (onPersonalToolbar) {
|
||||
button.classList.add("bookmark-item");
|
||||
button.classList.remove("toolbarbutton-1");
|
||||
this.button.classList.add("bookmark-item");
|
||||
this.button.classList.remove("toolbarbutton-1");
|
||||
}
|
||||
else {
|
||||
button.classList.remove("bookmark-item");
|
||||
button.classList.add("toolbarbutton-1");
|
||||
this.button.classList.remove("bookmark-item");
|
||||
this.button.classList.add("toolbarbutton-1");
|
||||
}
|
||||
},
|
||||
|
||||
@ -1107,9 +1130,8 @@ let BookmarkingUI = {
|
||||
// When an element with a placesView attached is removed and re-inserted,
|
||||
// XBL reapplies the binding causing any kind of issues and possible leaks,
|
||||
// so kill current view and let popupshowing generate a new one.
|
||||
let button = this.button;
|
||||
if (button && button._placesView)
|
||||
button._placesView.uninit();
|
||||
if (this.button._placesView)
|
||||
this.button._placesView.uninit();
|
||||
},
|
||||
|
||||
customizeStart: function BUI_customizeStart() {
|
||||
@ -1117,6 +1139,11 @@ let BookmarkingUI = {
|
||||
},
|
||||
|
||||
customizeChange: function BUI_customizeChange() {
|
||||
let usedToUpdateStarState = this._shouldUpdateStarState();
|
||||
this._updateCustomizationState();
|
||||
if (usedToUpdateStarState != this._shouldUpdateStarState()) {
|
||||
this.updateStarState();
|
||||
}
|
||||
this._updateToolbarStyle();
|
||||
},
|
||||
|
||||
@ -1127,10 +1154,12 @@ let BookmarkingUI = {
|
||||
|
||||
init: function() {
|
||||
CustomizableUI.addListener(this);
|
||||
this._updateCustomizationState();
|
||||
},
|
||||
|
||||
_hasBookmarksObserver: false,
|
||||
uninit: function BUI_uninit() {
|
||||
this._updateBookmarkPageMenuItem(true);
|
||||
CustomizableUI.removeListener(this);
|
||||
|
||||
this._uninitView();
|
||||
@ -1146,7 +1175,7 @@ let BookmarkingUI = {
|
||||
},
|
||||
|
||||
updateStarState: function BUI_updateStarState() {
|
||||
if (!this.button || (this._uri && gBrowser.currentURI.equals(this._uri))) {
|
||||
if (this._uri && gBrowser.currentURI.equals(this._uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1195,38 +1224,57 @@ let BookmarkingUI = {
|
||||
},
|
||||
|
||||
_updateStar: function BUI__updateStar() {
|
||||
let button = this.button;
|
||||
if (!button)
|
||||
if (!this._shouldUpdateStarState()) {
|
||||
if (this.button.hasAttribute("starred")) {
|
||||
this.button.removeAttribute("starred");
|
||||
this.button.removeAttribute("buttontooltiptext");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._itemIds.length > 0) {
|
||||
button.setAttribute("starred", "true");
|
||||
button.setAttribute("buttontooltiptext", this._starredTooltip);
|
||||
if (this._itemIds && this._itemIds.length > 0) {
|
||||
this.button.setAttribute("starred", "true");
|
||||
this.button.setAttribute("buttontooltiptext", this._starredTooltip);
|
||||
}
|
||||
else {
|
||||
button.removeAttribute("starred");
|
||||
button.setAttribute("buttontooltiptext", this._unstarredTooltip);
|
||||
this.button.removeAttribute("starred");
|
||||
this.button.setAttribute("buttontooltiptext", this._unstarredTooltip);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* forceReset is passed when we're destroyed and the label should go back
|
||||
* to the default (Bookmark This Page) for OS X.
|
||||
*/
|
||||
_updateBookmarkPageMenuItem: function BUI__updateBookmarkPageMenuItem(forceReset) {
|
||||
let isStarred = !forceReset && this._itemIds && this._itemIds.length > 0;
|
||||
let label = isStarred ? "editlabel" : "bookmarklabel";
|
||||
this.broadcaster.setAttribute("label", this.broadcaster.getAttribute(label));
|
||||
},
|
||||
|
||||
onMainMenuPopupShowing: function BUI_onMainMenuPopupShowing(event) {
|
||||
this._updateBookmarkPageMenuItem();
|
||||
PlacesCommandHook.updateBookmarkAllTabsCommand();
|
||||
},
|
||||
|
||||
onCommand: function BUI_onCommand(aEvent) {
|
||||
if (aEvent.target != aEvent.currentTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle special case when the button is in the panel.
|
||||
let widgetGroup = CustomizableUI.getWidget("bookmarks-menu-button");
|
||||
let widget = widgetGroup.forWindow(window);
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
let widget = CustomizableUI.getWidget("bookmarks-menu-button")
|
||||
.forWindow(window);
|
||||
if (this._currentAreaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
let view = document.getElementById("PanelUI-bookmarks");
|
||||
view.addEventListener("ViewShowing", this.onPanelMenuViewShowing);
|
||||
view.addEventListener("ViewHiding", this.onPanelMenuViewHiding);
|
||||
view.addEventListener("ViewShowing", this);
|
||||
view.addEventListener("ViewHiding", this);
|
||||
widget.node.setAttribute("closemenu", "none");
|
||||
PanelUI.showSubView("PanelUI-bookmarks", widget.node,
|
||||
CustomizableUI.AREA_PANEL);
|
||||
return;
|
||||
}
|
||||
else if (widget.overflowed) {
|
||||
if (widget.overflowed) {
|
||||
// Allow to close the panel if the page is already bookmarked, cause
|
||||
// we are going to open the edit bookmark panel.
|
||||
if (this._itemIds.length > 0)
|
||||
@ -1241,7 +1289,19 @@ let BookmarkingUI = {
|
||||
}
|
||||
},
|
||||
|
||||
handleEvent: function BUI_handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "ViewShowing":
|
||||
this.onPanelMenuViewShowing(aEvent);
|
||||
break;
|
||||
case "ViewHiding":
|
||||
this.onPanelMenuViewHiding(aEvent);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onPanelMenuViewShowing: function BUI_onViewShowing(aEvent) {
|
||||
this._updateBookmarkPageMenuItem();
|
||||
// Update checked status of the toolbar toggle.
|
||||
let viewToolbar = document.getElementById("panelMenu_viewBookmarksToolbar");
|
||||
let personalToolbar = document.getElementById("PersonalToolbar");
|
||||
@ -1257,11 +1317,13 @@ let BookmarkingUI = {
|
||||
mainLevel: "subviewbutton"
|
||||
}
|
||||
});
|
||||
aEvent.target.removeEventListener("ViewShowing", this);
|
||||
},
|
||||
|
||||
onPanelMenuViewHiding: function BUI_onViewHiding(aEvent) {
|
||||
this._panelMenuView.uninit();
|
||||
delete this._panelMenuView;
|
||||
aEvent.target.removeEventListener("ViewHiding", this);
|
||||
},
|
||||
|
||||
onPanelMenuViewCommand: function BUI_onPanelMenuViewCommand(aEvent, aView) {
|
||||
@ -1278,50 +1340,50 @@ let BookmarkingUI = {
|
||||
// nsINavBookmarkObserver
|
||||
onItemAdded: function BUI_onItemAdded(aItemId, aParentId, aIndex, aItemType,
|
||||
aURI) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aURI && aURI.equals(this._uri)) {
|
||||
// If a new bookmark has been added to the tracked uri, register it.
|
||||
if (this._itemIds.indexOf(aItemId) == -1) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStar();
|
||||
// Only need to update the UI if it wasn't marked as starred before:
|
||||
if (this._itemIds.length == 1) {
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onItemRemoved: function BUI_onItemRemoved(aItemId) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If one of the tracked bookmarks has been removed, unregister it.
|
||||
if (index != -1) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStar();
|
||||
// Only need to update the UI if the page is no longer starred
|
||||
if (this._itemIds.length == 0) {
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onItemChanged: function BUI_onItemChanged(aItemId, aProperty,
|
||||
aIsAnnotationProperty, aNewValue) {
|
||||
if (!this.button) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aProperty == "uri") {
|
||||
let index = this._itemIds.indexOf(aItemId);
|
||||
// If the changed bookmark was tracked, check if it is now pointing to
|
||||
// a different uri and unregister it.
|
||||
if (index != -1 && aNewValue != this._uri.spec) {
|
||||
this._itemIds.splice(index, 1);
|
||||
this._updateStar();
|
||||
// Only need to update the UI if the page is no longer starred
|
||||
if (this._itemIds.length == 0) {
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
// If another bookmark is now pointing to the tracked uri, register it.
|
||||
else if (index == -1 && aNewValue == this._uri.spec) {
|
||||
this._itemIds.push(aItemId);
|
||||
this._updateStar();
|
||||
// Only need to update the UI if it wasn't marked as starred before:
|
||||
if (this._itemIds.length == 1) {
|
||||
this._updateStar();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1334,23 +1396,30 @@ let BookmarkingUI = {
|
||||
|
||||
// CustomizableUI events:
|
||||
_starButtonLabel: null,
|
||||
_starButtonOverflowedLabel: null,
|
||||
get _starButtonOverflowedLabel() {
|
||||
delete this._starButtonOverflowedLabel;
|
||||
this._starButtonOverflowedLabel =
|
||||
gNavigatorBundle.getString("starButtonOverflowed.label");
|
||||
},
|
||||
get _starButtonOverflowedStarredLabel() {
|
||||
delete this._starButtonOverflowedStarredLabel;
|
||||
this._starButtonOverflowedStarredLabel =
|
||||
gNavigatorBundle.getString("starButtonOverflowedStarred.label");
|
||||
},
|
||||
onWidgetOverflow: function(aNode, aContainer) {
|
||||
let win = aNode.ownerDocument.defaultView;
|
||||
if (aNode.id != "bookmarks-menu-button" || win != window)
|
||||
return;
|
||||
|
||||
if (!this._starButtonOverflowedLabel) {
|
||||
this._starButtonOverflowedLabel = gNavigatorBundle.getString(
|
||||
"starButtonOverflowed.label");
|
||||
}
|
||||
|
||||
let currentLabel = aNode.getAttribute("label");
|
||||
if (!this._starButtonLabel)
|
||||
this._starButtonLabel = currentLabel;
|
||||
|
||||
if (currentLabel == this._starButtonLabel)
|
||||
aNode.setAttribute("label", this._starButtonOverflowedLabel);
|
||||
if (currentLabel == this._starButtonLabel) {
|
||||
let desiredLabel = this._itemIds.length > 0 ? this._starButtonOverflowedStarredLabel
|
||||
: this._starButtonOverflowedLabel;
|
||||
aNode.setAttribute("label", desiredLabel);
|
||||
}
|
||||
},
|
||||
|
||||
onWidgetUnderflow: function(aNode, aContainer) {
|
||||
@ -1360,10 +1429,10 @@ let BookmarkingUI = {
|
||||
|
||||
// If the button hasn't been in the overflow panel before, we may ignore
|
||||
// this event.
|
||||
if (!this._starButtonOverflowedLabel || !this._starButtonLabel)
|
||||
if (!this._starButtonLabel)
|
||||
return;
|
||||
|
||||
if (aNode.getAttribute("label") == this._starButtonOverflowedLabel)
|
||||
if (aNode.getAttribute("label") != this._starButtonLabel)
|
||||
aNode.setAttribute("label", this._starButtonLabel);
|
||||
},
|
||||
|
||||
|
@ -140,6 +140,11 @@
|
||||
type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/web-panels.xul"
|
||||
oncommand="toggleSidebar('viewWebPanelsSidebar');"/>
|
||||
|
||||
<broadcaster id="bookmarkThisPageBroadcaster"
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
bookmarklabel="&bookmarkThisPageCmd.label;"
|
||||
editlabel="&editThisBookmarkCmd.label;"/>
|
||||
|
||||
<!-- popup blocking menu items -->
|
||||
<broadcaster id="blockedPopupAllowSite"
|
||||
accesskey="&allowPopups.accesskey;"
|
||||
|
@ -389,12 +389,13 @@
|
||||
|
||||
<!-- Sync Panel -->
|
||||
<panel id="sync-start-panel" class="sync-panel" type="arrow" hidden="true"
|
||||
noautofocus="true" level="top" onclick="this.hidePopup();">
|
||||
noautofocus="true" level="top" onclick="this.hidePopup();"
|
||||
flip="slide">
|
||||
<hbox class="sync-panel-outer">
|
||||
<image class="sync-panel-icon"/>
|
||||
<vbox class="sync-panel-inner">
|
||||
<description id="sync-start-panel-title"
|
||||
value="&syncStartPanel.title;"/>
|
||||
value="&syncStartPanel.heading;"/>
|
||||
<description id="sync-start-panel-subtitle">
|
||||
#ifdef XP_UNIX
|
||||
&syncStartPanel.subTitleUnix;
|
||||
@ -408,29 +409,21 @@
|
||||
|
||||
<!-- Sync Error Panel -->
|
||||
<panel id="sync-error-panel" class="sync-panel" type="arrow" hidden="true"
|
||||
noautofocus="true" level="top" onclick="this.hidePopup();">
|
||||
noautofocus="true" level="top" onclick="this.hidePopup();"
|
||||
flip="slide">
|
||||
<hbox class="sync-panel-outer">
|
||||
<image class="sync-panel-icon"/>
|
||||
<vbox class="sync-panel-inner">
|
||||
<description id="sync-error-panel-title"
|
||||
value="&syncErrorPanel.title;"/>
|
||||
value="&syncErrorPanel.heading;"/>
|
||||
<description id="sync-error-panel-subtitle"
|
||||
value="&syncErrorPanel.subTitle;"/>
|
||||
<hbox class="sync-panel-button-box">
|
||||
<button class="sync-panel-button"
|
||||
#ifdef XP_UNIX
|
||||
label="&syncErrorPanel.prefButtonUnix.label;"
|
||||
accesskey="&syncErrorPanel.prefButtonUnix.accesskey;"
|
||||
#else
|
||||
label="&syncErrorPanel.prefButton.label;"
|
||||
accesskey="&syncErrorPanel.prefButton.accesskey;"
|
||||
#endif
|
||||
onclick="gFxAccounts.openPreferences();"/>
|
||||
<spacer flex="1"/>
|
||||
<button class="sync-panel-button"
|
||||
label="&syncErrorPanel.signInButton.label;"
|
||||
accesskey="&syncErrorPanel.signInButton.accesskey;"
|
||||
onclick="gFxAccounts.openSignInPage();"/>
|
||||
onclick="gFxAccounts.openSignInAgainPage();"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
@ -32,9 +32,9 @@
|
||||
<label id="sync-customize-title" value="&syncCustomize.title;"/>
|
||||
<description id="sync-customize-subtitle"
|
||||
#ifdef XP_UNIX
|
||||
value="&syncCustomize.subTitleUnix;"
|
||||
value="&syncCustomizeUnix.description;"
|
||||
#else
|
||||
value="&syncCustomize.subTitle;"
|
||||
value="&syncCustomize.description;"
|
||||
#endif
|
||||
/>
|
||||
|
||||
|
@ -11,7 +11,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
// Ensure we don't pollute prefs for next tests.
|
||||
Services.prefs.clearUserPref("identity.fxaccounts.enabled");
|
||||
Services.prefs.clearUserPref("identity.fxaccounts.remote.uri");
|
||||
});
|
||||
|
||||
@ -21,7 +20,6 @@ let gTests = [
|
||||
desc: "Test the remote commands",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setBoolPref("identity.fxaccounts.enabled", true);
|
||||
Services.prefs.setCharPref("identity.fxaccounts.remote.uri",
|
||||
"https://example.com/browser/browser/base/content/test/general/accounts_testRemoteCommands.html");
|
||||
},
|
||||
|
@ -50,15 +50,18 @@ browser.jar:
|
||||
content/browser/abouthealthreport/abouthealth.js (content/abouthealthreport/abouthealth.js)
|
||||
content/browser/abouthealthreport/abouthealth.css (content/abouthealthreport/abouthealth.css)
|
||||
#endif
|
||||
content/browser/aboutaccounts/aboutaccounts.xhtml (content/aboutaccounts/aboutaccounts.xhtml)
|
||||
content/browser/aboutaccounts/aboutaccounts.js (content/aboutaccounts/aboutaccounts.js)
|
||||
content/browser/aboutaccounts/aboutaccounts.css (content/aboutaccounts/aboutaccounts.css)
|
||||
content/browser/aboutaccounts/main.css (content/aboutaccounts/main.css)
|
||||
content/browser/aboutaccounts/normalize.css (content/aboutaccounts/normalize.css)
|
||||
content/browser/aboutaccounts/fonts.css (content/aboutaccounts/fonts.css)
|
||||
content/browser/aboutaccounts/images/fox.png (content/aboutaccounts/images/fox.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro.png (content/aboutaccounts/images/graphic_sync_intro.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro@2x.png (content/aboutaccounts/images/graphic_sync_intro@2x.png)
|
||||
content/browser/aboutaccounts/aboutaccounts.xhtml (content/aboutaccounts/aboutaccounts.xhtml)
|
||||
content/browser/aboutaccounts/aboutaccounts.js (content/aboutaccounts/aboutaccounts.js)
|
||||
content/browser/aboutaccounts/aboutaccounts.css (content/aboutaccounts/aboutaccounts.css)
|
||||
content/browser/aboutaccounts/main.css (content/aboutaccounts/main.css)
|
||||
content/browser/aboutaccounts/normalize.css (content/aboutaccounts/normalize.css)
|
||||
content/browser/aboutaccounts/fonts.css (content/aboutaccounts/fonts.css)
|
||||
content/browser/aboutaccounts/fonts/clearsans-regular.woff (content/aboutaccounts/fonts/clearsans-regular.woff)
|
||||
content/browser/aboutaccounts/fonts/firasans-light.woff (content/aboutaccounts/fonts/firasans-light.woff)
|
||||
content/browser/aboutaccounts/fonts/firasans-regular.woff (content/aboutaccounts/fonts/firasans-regular.woff)
|
||||
content/browser/aboutaccounts/images/fox.png (content/aboutaccounts/images/fox.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro.png (content/aboutaccounts/images/graphic_sync_intro.png)
|
||||
content/browser/aboutaccounts/images/graphic_sync_intro@2x.png (content/aboutaccounts/images/graphic_sync_intro@2x.png)
|
||||
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
|
@ -18,7 +18,7 @@
|
||||
<toolbarbutton id="PanelUI-fxa-status"
|
||||
defaultlabel="&fxaSignIn.label;"
|
||||
errorlabel="&fxaSignInError.label;"
|
||||
oncommand="gFxAccounts.toggle(event);"
|
||||
oncommand="gFxAccounts.onMenuPanelCommand(event);"
|
||||
hidden="true"/>
|
||||
|
||||
<hbox id="PanelUI-footer-inner">
|
||||
@ -88,8 +88,8 @@
|
||||
<panelview id="PanelUI-bookmarks" flex="1" class="PanelUI-subView">
|
||||
<label value="&bookmarksMenu.label;" class="panel-subview-header"/>
|
||||
<toolbarbutton id="panelMenuBookmarkThisPage"
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
class="subviewbutton"
|
||||
observes="bookmarkThisPageBroadcaster"
|
||||
command="Browser:AddBookmarkAs"
|
||||
onclick="PanelUI.hide();"/>
|
||||
<toolbarseparator/>
|
||||
|
@ -256,8 +256,12 @@ let gSyncPane = {
|
||||
window.close();
|
||||
},
|
||||
|
||||
signIn: function() {
|
||||
this.openContentInBrowser("about:accounts?action=signin");
|
||||
},
|
||||
|
||||
reSignIn: function() {
|
||||
this.openContentInBrowser("about:accounts");
|
||||
this.openContentInBrowser("about:accounts?action=reauth");
|
||||
},
|
||||
|
||||
manageFirefoxAccount: function() {
|
||||
@ -290,17 +294,19 @@ let gSyncPane = {
|
||||
// We use a string bundle shared with aboutAccounts.
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/syncSetup.properties");
|
||||
let continueLabel = sb.GetStringFromName("continue.label");
|
||||
let title = sb.GetStringFromName("unlink.verify.title");
|
||||
let body = sb.GetStringFromName("unlink.verify.heading") +
|
||||
let title = sb.GetStringFromName("disconnect.verify.title");
|
||||
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
let brandShortName = brandBundle.GetStringFromName("brandShortName");
|
||||
let body = sb.GetStringFromName("disconnect.verify.heading") +
|
||||
"\n\n" +
|
||||
sb.GetStringFromName("unlink.verify.description");
|
||||
sb.formatStringFromName("disconnect.verify.description",
|
||||
[brandShortName], 1);
|
||||
let ps = Services.prompt;
|
||||
let buttonFlags = (ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING) +
|
||||
(ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
|
||||
ps.BUTTON_POS_1_DEFAULT;
|
||||
let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
|
||||
continueLabel, null, null, null,
|
||||
{});
|
||||
continueLabel, null, null, null, {});
|
||||
if (pressed != 0) { // 0 is the "continue" button
|
||||
return;
|
||||
}
|
||||
|
@ -188,8 +188,11 @@
|
||||
<vbox id="noFxaAccount">
|
||||
<description>&welcome.description;</description>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.openContentInBrowser('about:accounts?signin=true'); return false;"
|
||||
value="&welcome.startButton.label;"/>
|
||||
onclick="gSyncPane.signIn(); return false;"
|
||||
value="&welcome.createAccount.label;"/>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.signIn(); return false;"
|
||||
value="&welcome.signIn.label;"/>
|
||||
<spacer flex="1"/>
|
||||
<label class="text-link"
|
||||
onclick="gSyncPane.openOldSyncSupportPage(); return false;"
|
||||
@ -199,7 +202,7 @@
|
||||
|
||||
<vbox id="hasFxaAccount">
|
||||
<groupbox id="fxaGroup">
|
||||
<caption label="&syncBrand.fxa-singular.label;"/>
|
||||
<caption label="&syncBrand.fxAccount.label;"/>
|
||||
|
||||
<deck id="fxaLoginStatus">
|
||||
|
||||
@ -212,7 +215,7 @@
|
||||
<spacer flex="1"/>
|
||||
<vbox align="end">
|
||||
<button onclick="gSyncPane.unlinkFirefoxAccount(true);"
|
||||
label="&unlink.label;" />
|
||||
label="&disconnect.label;" />
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
|
@ -43,6 +43,22 @@ function setupAutoCompletion(ctx, walker) {
|
||||
return;
|
||||
}
|
||||
|
||||
return win.CodeMirror.Pass;
|
||||
},
|
||||
"Up": cm => {
|
||||
if (popup && popup.isOpen) {
|
||||
cycleSuggestions(ed, true);
|
||||
return;
|
||||
}
|
||||
|
||||
return win.CodeMirror.Pass;
|
||||
},
|
||||
"Down": cm => {
|
||||
if (popup && popup.isOpen) {
|
||||
cycleSuggestions(ed);
|
||||
return;
|
||||
}
|
||||
|
||||
return win.CodeMirror.Pass;
|
||||
},
|
||||
};
|
||||
@ -147,8 +163,9 @@ function cycleSuggestions(ed, reverse) {
|
||||
function onEditorKeypress(ed, event) {
|
||||
let private = privates.get(ed);
|
||||
switch (event.keyCode) {
|
||||
case event.DOM_VK_UP:
|
||||
case event.DOM_VK_DOWN:
|
||||
case event.DOM_VK_ESCAPE:
|
||||
if (private.popup.isOpen)
|
||||
event.preventDefault();
|
||||
case event.DOM_VK_LEFT:
|
||||
case event.DOM_VK_RIGHT:
|
||||
case event.DOM_VK_HOME:
|
||||
@ -157,7 +174,6 @@ function onEditorKeypress(ed, event) {
|
||||
case event.DOM_VK_DELETE:
|
||||
case event.DOM_VK_ENTER:
|
||||
case event.DOM_VK_RETURN:
|
||||
case event.DOM_VK_ESCAPE:
|
||||
private.doNotAutocomplete = true;
|
||||
private.popup.hidePopup();
|
||||
break;
|
||||
|
@ -22,6 +22,8 @@ let TEST_CASES = [
|
||||
['VK_RIGHT', -1],
|
||||
['VK_RIGHT', -1],
|
||||
[-1, 1, 0],
|
||||
['VK_LEFT', -1],
|
||||
['VK_RIGHT', -1],
|
||||
['VK_DOWN', -1],
|
||||
['VK_RIGHT', -1],
|
||||
['VK_RIGHT', -1],
|
||||
@ -31,14 +33,18 @@ let TEST_CASES = [
|
||||
['VK_RETURN', -1],
|
||||
['b', MAX_SUGGESTIONS, 0],
|
||||
['a', 11, 0],
|
||||
['VK_TAB', 11, 0, 1],
|
||||
['VK_DOWN', 11, 0, 1],
|
||||
['VK_TAB', 11, 1, 1],
|
||||
[':', -1],
|
||||
['b', 9, 0],
|
||||
['l', 4, 0],
|
||||
['VK_TAB', 4, 0, 1],
|
||||
['VK_DOWN', 4, 1, 1],
|
||||
['VK_UP', 4, 0, 1],
|
||||
['VK_TAB', 4, 1, 1],
|
||||
['VK_TAB', 4, 2, 1],
|
||||
['VK_LEFT', -1],
|
||||
['VK_RIGHT', -1],
|
||||
['VK_DOWN', -1],
|
||||
['VK_RETURN', -1],
|
||||
['b', 2, 0],
|
||||
@ -102,12 +108,13 @@ function testState() {
|
||||
key = " ";
|
||||
mods.accelKey = true;
|
||||
}
|
||||
else if (/(down|left|right|return|home|end)/ig.test(key)) {
|
||||
else if (/(left|right|return|home|end)/ig.test(key) ||
|
||||
(key == "VK_DOWN" && !gPopup.isOpen)) {
|
||||
info("pressing key " + key + " to get result: [" + TEST_CASES[index] +
|
||||
"] for index " + index);
|
||||
gEditor.once("cursorActivity", checkState);
|
||||
}
|
||||
else if (key == "VK_TAB") {
|
||||
else if (key == "VK_TAB" || key == "VK_UP" || key == "VK_DOWN") {
|
||||
info("pressing key " + key + " to get result: [" + TEST_CASES[index] +
|
||||
"] for index " + index);
|
||||
gEditor.once("suggestion-entered", checkState);
|
||||
@ -139,8 +146,7 @@ function checkState() {
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok(gPopup._panel.state != "open" && gPopup._panel.state != "showing",
|
||||
"Popup is closed for index " + index);
|
||||
ok(!gPopup.isOpen, "Popup is closed for index " + index);
|
||||
}
|
||||
index++;
|
||||
testState();
|
||||
|
@ -2,8 +2,9 @@
|
||||
- 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 aboutAccounts.pageTitle "Welcome to Sync">
|
||||
<!ENTITY aboutAccounts.welcome "Welcome to &syncBrand.shortName.label;">
|
||||
|
||||
<!ENTITY aboutAccountsConfig.description "Sign in to sync your tabs, bookmarks, passwords & more.">
|
||||
<!ENTITY aboutAccountsConfig.startButton.label "Get started">
|
||||
<!ENTITY aboutAccountsConfig.useOldSync.label "Using an older version of Sync?">
|
||||
<!ENTITY aboutAccountsConfig.manage.label "Manage">
|
||||
|
@ -98,15 +98,11 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
|
||||
<!ENTITY fxaSignIn.label "Sign in to &syncBrand.shortName.label;">
|
||||
<!ENTITY fxaSignInError.label "Reconnect to &syncBrand.shortName.label;">
|
||||
<!ENTITY syncStartPanel.title "&brandShortName; is now syncing.">
|
||||
<!ENTITY syncStartPanel.heading "&brandShortName; is now syncing">
|
||||
<!ENTITY syncStartPanel.subTitle "You can manage &syncBrand.shortName.label; in Options.">
|
||||
<!ENTITY syncStartPanel.subTitleUnix "You can manage &syncBrand.shortName.label; in Preferences.">
|
||||
<!ENTITY syncErrorPanel.title "Cannot connect to &syncBrand.shortName.label;">
|
||||
<!ENTITY syncErrorPanel.heading "Cannot connect to &syncBrand.shortName.label;">
|
||||
<!ENTITY syncErrorPanel.subTitle "Please sign in to resume syncing.">
|
||||
<!ENTITY syncErrorPanel.prefButton.label "Options">
|
||||
<!ENTITY syncErrorPanel.prefButton.accesskey "O">
|
||||
<!ENTITY syncErrorPanel.prefButtonUnix.label "Preferences">
|
||||
<!ENTITY syncErrorPanel.prefButtonUnix.accesskey "P">
|
||||
<!ENTITY syncErrorPanel.signInButton.label "Sign In">
|
||||
<!ENTITY syncErrorPanel.signInButton.accesskey "S">
|
||||
|
||||
@ -131,6 +127,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||
<!ENTITY bookmarksMenu.label "Bookmarks">
|
||||
<!ENTITY bookmarksMenu.accesskey "B">
|
||||
<!ENTITY bookmarkThisPageCmd.label "Bookmark This Page">
|
||||
<!ENTITY editThisBookmarkCmd.label "Edit This Bookmark">
|
||||
<!ENTITY bookmarkThisPageCmd.commandkey "d">
|
||||
<!ENTITY markPageCmd.commandkey "l">
|
||||
<!ENTITY sharePageCmd.label "Share This Page">
|
||||
|
@ -240,6 +240,7 @@ bookmarksMenuButton.tooltip=Show your bookmarks (%S)
|
||||
starButtonOn.tooltip=Edit this bookmark
|
||||
starButtonOff.tooltip=Bookmark this page
|
||||
starButtonOverflowed.label=Bookmark This Page
|
||||
starButtonOverflowedStarred.label=Edit This Bookmark
|
||||
|
||||
# Print button tooltip on OS X
|
||||
# LOCALIZATION NOTE (printButton.tooltip):
|
||||
|
@ -140,4 +140,4 @@ shouldRestartTitle=Restart %S
|
||||
firefoxAccountsVerificationSentTitle=Verification Sent
|
||||
# LOCALIZATION NOTE: %S = user's email address.
|
||||
firefoxAccountsVerificationSentHeading=A verification link has been sent to %S
|
||||
firefoxAccountVerificationSentDescription=Please check your email and click the verification link to begin syncing.
|
||||
firefoxAccountVerificationSentDescription=Please check your email and click the link to begin syncing.
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
<!-- Firefox Accounts stuff -->
|
||||
<!ENTITY fxaPrivacyNotice.link.label "Privacy Notice">
|
||||
<!ENTITY determiningStatus.label "Determining your Firefox Account status…">
|
||||
<!ENTITY determiningStatus.label "Determining your Firefox Account status…">
|
||||
<!ENTITY signedInUnverified.beforename.label "">
|
||||
<!ENTITY signedInUnverified.aftername.label "is not verified.">
|
||||
|
||||
@ -58,10 +58,12 @@
|
||||
<!ENTITY notSignedIn.label "You are not signed in.">
|
||||
<!ENTITY signIn.label "Sign in">
|
||||
<!ENTITY manage.label "Manage">
|
||||
<!ENTITY unlink.label "Unlink this Browser…">
|
||||
<!ENTITY disconnect.label "Disconnect…">
|
||||
<!ENTITY verify.label "Verify Email">
|
||||
<!ENTITY forget.label "Forget this Email">
|
||||
|
||||
<!ENTITY welcome.description "Access your tabs, bookmarks, passwords and more wherever you use &brandShortName;.">
|
||||
<!ENTITY welcome.startButton.label "Sign in or Create an Account">
|
||||
<!ENTITY welcome.signIn.label "Sign In">
|
||||
<!ENTITY welcome.createAccount.label "Create Account">
|
||||
|
||||
<!ENTITY welcome.useOldSync.label "Using an older version of Sync?">
|
||||
|
@ -4,5 +4,4 @@
|
||||
|
||||
<!ENTITY syncBrand.shortName.label "Sync">
|
||||
<!ENTITY syncBrand.fullName.label "Firefox Sync">
|
||||
<!ENTITY syncBrand.fxa-singular.label "Firefox Account">
|
||||
<!ENTITY syncBrand.fxa-plural.label "Firefox Accounts">
|
||||
<!ENTITY syncBrand.fxAccount.label "Firefox Account">
|
||||
|
@ -6,8 +6,8 @@
|
||||
<!ENTITY syncCustomize.acceptButton.label "Start">
|
||||
|
||||
<!ENTITY syncCustomize.title "What would you like to sync?">
|
||||
<!ENTITY syncCustomize.subTitle "You can manage this selection in Options.">
|
||||
<!ENTITY syncCustomize.subTitleUnix "You can manage this selection in Preferences.">
|
||||
<!ENTITY syncCustomize.description "You can change this selection in Options.">
|
||||
<!ENTITY syncCustomizeUnix.description "You can change this selection in Preferences.">
|
||||
|
||||
<!--
|
||||
These engine names are the same as in browser/preferences/sync.dtd except
|
||||
|
@ -52,14 +52,15 @@ existingAccount.change.label = You can change this preference by selecting Sync
|
||||
|
||||
# Firefox Accounts based setup.
|
||||
continue.label = Continue
|
||||
unlink.verify.title = Unlink Browser
|
||||
unlink.verify.heading = Are you sure?
|
||||
unlink.verify.description = This browser will stop syncing with your other computers, but won't delete any of your local browsing data.
|
||||
|
||||
relink.verify.title = Merge Warning
|
||||
relink.verify.heading = Are you sure you want to sign in to Sync?
|
||||
# LOCALIZATION NOTE (relink.verify.description): Email address of a user previously signed into sync.
|
||||
relink.verify.description = A different user was previously signed in to Sync on this device. Signing in will merge this browser's bookmarks, passwords and other settings with %S
|
||||
disconnect.verify.title = Disconnect
|
||||
disconnect.verify.heading = Are you sure?
|
||||
# LOCALIZATION NOTE (disconnect.verify.description): %S will be replaced with
|
||||
# brandShortName
|
||||
disconnect.verify.description = %S will stop syncing with your account, but won’t delete any of your browsing data on this computer.
|
||||
|
||||
relinkVerify.title = Merge Warning
|
||||
relinkVerify.heading = Are you sure you want to sign in to Sync?
|
||||
# LOCALIZATION NOTE (relinkVerify.description): Email address of a user previously signed into sync.
|
||||
relinkVerify.description = A different user was previously signed in to Sync on this computer. Signing in will merge this browser’s bookmarks, passwords and other settings with %S
|
||||
|
||||
manage.pageTitle = Manage Sync
|
||||
|
@ -20,9 +20,10 @@
|
||||
<hbox id="start-container">
|
||||
<box id="instruction-topsites-box" insertafter="start-topsites" class="firstrun">
|
||||
<box id="instruction-topsites">
|
||||
<vbox align="center">
|
||||
<vbox class="instruction-content-container">
|
||||
<image class="instruction-arrow arrow-left-straight" />
|
||||
<image class="instruction-arrow arrow-left" />
|
||||
<label class="instruction-label" value="&firstRunTopSites.label;"/>
|
||||
<label class="instruction-label">&firstRunTopSites.label;</label>
|
||||
</vbox>
|
||||
</box>
|
||||
</box>
|
||||
@ -35,32 +36,32 @@
|
||||
|
||||
<box insertafter="start-bookmarks" class="firstrun">
|
||||
<box id="instruction-bookmarks">
|
||||
<vbox align="center">
|
||||
<vbox class="instruction-content-container" align="center">
|
||||
<image class="instruction-arrow arrow-right" />
|
||||
<label class="instruction-label" value="&firstRunBookmarks.label;"/>
|
||||
<label class="instruction-label">&firstRunBookmarks.label;</label>
|
||||
</vbox>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<box id="instruction-history-container" insertafter="start-history" class="firstrun">
|
||||
<box id="instruction-history">
|
||||
<vbox align="center">
|
||||
<vbox class="instruction-content-container" align="center">
|
||||
<image class="instruction-arrow arrow-right" />
|
||||
<label class="instruction-label" value="&firstRunHistory.label;"/>
|
||||
<label class="instruction-label">&firstRunHistory.label;</label>
|
||||
</vbox>
|
||||
</box>
|
||||
</box>
|
||||
|
||||
<box id="instruction-tabs" class="firstrun">
|
||||
<vbox align="center">
|
||||
<vbox class="instruction-content-container" align="center">
|
||||
<image class="instruction-arrow arrow-top" />
|
||||
<label class="instruction-label" value="&firstRunTabs.label;"/>
|
||||
<label class="instruction-label">&firstRunTabs.label;</label>
|
||||
</vbox>
|
||||
</box>
|
||||
|
||||
<box id="instruction-menu" class="firstrun">
|
||||
<hbox>
|
||||
<label class="instruction-label" value="&firstRunMenu.label;"/>
|
||||
<hbox class="instruction-content-container" align="right">
|
||||
<label class="instruction-label">&firstRunMenu.label;</label>
|
||||
<image class="instruction-arrow arrow-down" />
|
||||
</hbox>
|
||||
</box>
|
||||
|
@ -73,6 +73,10 @@ below instruction */
|
||||
|
||||
/* Instructions ---------------------- */
|
||||
|
||||
.instruction-content-container {
|
||||
width: 380px;
|
||||
}
|
||||
|
||||
.instruction-label {
|
||||
font-size: 16px;
|
||||
color: #808080;
|
||||
@ -94,7 +98,9 @@ below instruction */
|
||||
}
|
||||
|
||||
.instruction-arrow.arrow-left,
|
||||
.instruction-arrow.arrow-right {
|
||||
.instruction-arrow.arrow-right,
|
||||
.instruction-arrow.arrow-left-straight,
|
||||
.instruction-arrow.arrow-right-straight {
|
||||
background-image: url("chrome://browser/skin/images/arrow-left.png");
|
||||
}
|
||||
|
||||
@ -102,6 +108,14 @@ below instruction */
|
||||
transform: rotate(180deg) scaleY(-1);
|
||||
}
|
||||
|
||||
.instruction-arrow.arrow-left-straight {
|
||||
transform: rotate(220deg) scaleX(-1);
|
||||
}
|
||||
|
||||
.instruction-arrow.arrow-right-straight {
|
||||
transform: rotate(-220deg);
|
||||
}
|
||||
|
||||
#instruction-tabs {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
@ -114,13 +128,35 @@ below instruction */
|
||||
|
||||
#start-container[viewstate="landscape"] #instruction-topsites {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
transform: translateX(-50%);
|
||||
margin-left: 20px;
|
||||
bottom: 15%;
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-topsites {
|
||||
transform: translateX(calc(150px + 50%)) translateY(-60px);
|
||||
#start-container[viewstate="landscape"] #instruction-topsites .instruction-content-container {
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-topsites-box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-topsites .instruction-content-container {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-topsites .arrow-left-straight {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-topsites .arrow-left {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#start-container[viewstate="landscape"] #instruction-topsites .arrow-left-straight {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#start-container[viewstate="landscape"] #instruction-topsites .arrow-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#start-container[viewstate="landscape"] #instruction-history,
|
||||
@ -131,7 +167,8 @@ below instruction */
|
||||
}
|
||||
|
||||
#start-container[viewstate="portrait"] #instruction-history,
|
||||
#start-container[viewstate="portrait"] #instruction-bookmarks {
|
||||
#start-container[viewstate="portrait"] #instruction-bookmarks,
|
||||
#start-container[viewstate="portrait"] #instruction-topsites {
|
||||
transform: translateX(-55px);
|
||||
}
|
||||
|
||||
@ -147,6 +184,10 @@ below instruction */
|
||||
transform: translateY(40px);
|
||||
}
|
||||
|
||||
#start-container #instruction-menu .instruction-label {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#start-container[viewstate="landscape"] #start-history {
|
||||
padding-left: 50px;
|
||||
}
|
||||
|
@ -1682,10 +1682,6 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
||||
|
||||
/* Sync Panel */
|
||||
|
||||
.sync-panel {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sync-panel-icon {
|
||||
width: 32px;
|
||||
background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
|
||||
@ -1700,7 +1696,8 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#sync-error-panel-title {
|
||||
#sync-error-panel-title,
|
||||
#sync-start-panel-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -962,10 +962,6 @@ toolbar .toolbarbutton-1:not([type="menu-button"]),
|
||||
-moz-image-region: rect(0px, 320px, 64px, 256px);
|
||||
}
|
||||
|
||||
#bookmarks-menu-button[starred][cui-areatype="menu-panel"] {
|
||||
-moz-image-region: rect(0px, 384px, 64px, 320px);
|
||||
}
|
||||
|
||||
#history-panelmenu[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #history-panelmenu {
|
||||
-moz-image-region: rect(0px, 448px, 64px, 384px);
|
||||
@ -3601,10 +3597,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
|
||||
/* Sync Panels */
|
||||
|
||||
.sync-panel {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sync-panel-icon {
|
||||
width: 32px;
|
||||
background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
|
||||
@ -3641,7 +3633,8 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
|
||||
@hudButtonFocused@
|
||||
}
|
||||
|
||||
#sync-error-panel-title {
|
||||
#sync-error-panel-title,
|
||||
#sync-start-panel-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,6 @@ toolbarpaletteitem[place="palette"] > #bookmarks-menu-button {
|
||||
-moz-image-region: rect(0px, 160px, 32px, 128px);
|
||||
}
|
||||
|
||||
#bookmarks-menu-button[starred][cui-areatype="menu-panel"] {
|
||||
-moz-image-region: rect(0px, 192px, 32px, 160px);
|
||||
}
|
||||
|
||||
#history-panelmenu[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #history-panelmenu {
|
||||
-moz-image-region: rect(0px, 224px, 32px, 192px);
|
||||
|
@ -2144,10 +2144,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
|
||||
/* Sync Panel */
|
||||
|
||||
.sync-panel {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sync-panel-icon {
|
||||
width: 32px;
|
||||
background: url("chrome://browser/content/abouthome/sync.png") top left no-repeat;
|
||||
@ -2162,7 +2158,8 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#sync-error-panel-title {
|
||||
#sync-error-panel-title,
|
||||
#sync-start-panel-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
@ -403,7 +403,7 @@ CSPRep.fromString = function(aStr, self, reportOnly, docRequest, csp) {
|
||||
// relative to "self", but we should let devs know if the scheme is
|
||||
// abnormal and may fail a POST.
|
||||
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotHttpsOrHttp",
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotHttpsOrHttp2",
|
||||
[uri.asciiSpec]));
|
||||
}
|
||||
} catch(e) {
|
||||
@ -651,7 +651,7 @@ CSPRep.fromStringSpecCompliant = function(aStr, self, reportOnly, docRequest, cs
|
||||
// relative to "self", but we should let devs know if the scheme is
|
||||
// abnormal and may fail a POST.
|
||||
if (!uri.schemeIs("http") && !uri.schemeIs("https")) {
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotHttpsOrHttp",
|
||||
cspWarn(aCSPR, CSPLocalizer.getFormatStr("reportURInotHttpsOrHttp2",
|
||||
[uri.asciiSpec]));
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -25,9 +25,9 @@ couldNotProcessUnknownDirective = Couldn't process unknown directive '%1$S'
|
||||
# LOCALIZATION NOTE (ignoringUnknownOption):
|
||||
# %1$S is the option that could not be understood
|
||||
ignoringUnknownOption = Ignoring unknown option %1$S
|
||||
# LOCALIZATION NOTE (reportURInotHttpsOrHttp):
|
||||
# LOCALIZATION NOTE (reportURInotHttpsOrHttp2):
|
||||
# %1$S is the ETLD of the report URI that is not HTTP or HTTPS
|
||||
reportURInotHttpsOrHttp = The report URI (%1$) should be an HTTP or HTTPS URI.
|
||||
reportURInotHttpsOrHttp2 = The report URI (%1$S) should be an HTTP or HTTPS URI.
|
||||
# LOCALIZATION NOTE (pageCannotSendReportsTo):
|
||||
# %1$S is the URI of the page with the policy
|
||||
# %2$S is the report URI that could not be used
|
||||
|
@ -2482,7 +2482,11 @@ abstract public class BrowserApp extends GeckoApp
|
||||
// HomePager.OnUrlOpenListener
|
||||
@Override
|
||||
public void onUrlOpen(String url, EnumSet<OnUrlOpenListener.Flags> flags) {
|
||||
if (!maybeSwitchToTab(url, flags)) {
|
||||
if (flags.contains(OnUrlOpenListener.Flags.OPEN_WITH_INTENT)) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(url));
|
||||
startActivity(intent);
|
||||
} else if (!maybeSwitchToTab(url, flags)) {
|
||||
openUrlAndStopEditing(url);
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public class DynamicPanel extends HomeFragment {
|
||||
switch(mPanelConfig.getLayoutType()) {
|
||||
case FRAME:
|
||||
final PanelDatasetHandler datasetHandler = new PanelDatasetHandler();
|
||||
mLayout = new FramePanelLayout(getActivity(), mPanelConfig, datasetHandler);
|
||||
mLayout = new FramePanelLayout(getActivity(), mPanelConfig, datasetHandler, mUrlOpenListener);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.HomeConfig.PanelConfig;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
|
||||
@ -18,8 +19,8 @@ class FramePanelLayout extends PanelLayout {
|
||||
private final View mChildView;
|
||||
private final ViewConfig mChildConfig;
|
||||
|
||||
public FramePanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler) {
|
||||
super(context, panelConfig, datasetHandler);
|
||||
public FramePanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler, OnUrlOpenListener urlOpenListener) {
|
||||
super(context, panelConfig, datasetHandler, urlOpenListener);
|
||||
|
||||
// This layout can only hold one view so we simply
|
||||
// take the first defined view from PanelConfig.
|
||||
|
@ -30,7 +30,7 @@ public class HomeListView extends ListView
|
||||
private HomeContextMenuInfo mContextMenuInfo;
|
||||
|
||||
// On URL open listener
|
||||
private OnUrlOpenListener mUrlOpenListener;
|
||||
protected OnUrlOpenListener mUrlOpenListener;
|
||||
|
||||
// Top divider
|
||||
private boolean mShowTopDivider;
|
||||
|
@ -68,7 +68,8 @@ public class HomePager extends ViewPager {
|
||||
|
||||
public interface OnUrlOpenListener {
|
||||
public enum Flags {
|
||||
ALLOW_SWITCH_TO_TAB
|
||||
ALLOW_SWITCH_TO_TAB,
|
||||
OPEN_WITH_INTENT
|
||||
}
|
||||
|
||||
public void onUrlOpen(String url, EnumSet<Flags> flags);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.HomeConfig.PanelConfig;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
|
||||
@ -58,6 +59,7 @@ abstract class PanelLayout extends FrameLayout {
|
||||
|
||||
private final List<ViewEntry> mViewEntries;
|
||||
private final DatasetHandler mDatasetHandler;
|
||||
private final OnUrlOpenListener mUrlOpenListener;
|
||||
|
||||
/**
|
||||
* To be used by panel views to express that they are
|
||||
@ -86,10 +88,15 @@ abstract class PanelLayout extends FrameLayout {
|
||||
public void resetDataset(String datasetId);
|
||||
}
|
||||
|
||||
public PanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler) {
|
||||
public interface PanelView {
|
||||
public void setOnUrlOpenListener(OnUrlOpenListener listener);
|
||||
}
|
||||
|
||||
public PanelLayout(Context context, PanelConfig panelConfig, DatasetHandler datasetHandler, OnUrlOpenListener urlOpenListener) {
|
||||
super(context);
|
||||
mViewEntries = new ArrayList<ViewEntry>();
|
||||
mDatasetHandler = datasetHandler;
|
||||
mUrlOpenListener = urlOpenListener;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,6 +162,8 @@ abstract class PanelLayout extends FrameLayout {
|
||||
final ViewEntry entry = new ViewEntry(view, viewConfig);
|
||||
mViewEntries.add(entry);
|
||||
|
||||
((PanelView) view).setOnUrlOpenListener(mUrlOpenListener);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@ -228,4 +237,4 @@ abstract class PanelLayout extends FrameLayout {
|
||||
return mViewConfig.getDatasetId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ package org.mozilla.gecko.home;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.home.HomeConfig.ViewConfig;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
import org.mozilla.gecko.home.PanelLayout.DatasetBacked;
|
||||
import org.mozilla.gecko.home.PanelLayout.PanelView;
|
||||
import org.mozilla.gecko.db.BrowserContract.HomeItems;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
@ -16,9 +19,12 @@ import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class PanelListView extends HomeListView
|
||||
implements DatasetBacked {
|
||||
implements DatasetBacked, PanelView {
|
||||
|
||||
private static final String LOGTAG = "GeckoPanelListView";
|
||||
|
||||
@ -30,6 +36,7 @@ public class PanelListView extends HomeListView
|
||||
mViewConfig = viewConfig;
|
||||
mAdapter = new PanelListAdapter(context);
|
||||
setAdapter(mAdapter);
|
||||
setOnItemClickListener(new PanelListItemClickListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -54,4 +61,19 @@ public class PanelListView extends HomeListView
|
||||
return LayoutInflater.from(parent.getContext()).inflate(R.layout.panel_list_row, parent, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PanelListItemClickListener implements AdapterView.OnItemClickListener {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Cursor cursor = mAdapter.getCursor();
|
||||
if (cursor == null || !cursor.moveToPosition(position)) {
|
||||
throw new IllegalStateException("Couldn't move cursor to position " + position);
|
||||
}
|
||||
|
||||
int urlIndex = cursor.getColumnIndexOrThrow(HomeItems.URL);
|
||||
final String url = cursor.getString(urlIndex);
|
||||
|
||||
mUrlOpenListener.onUrlOpen(url, EnumSet.of(OnUrlOpenListener.Flags.OPEN_WITH_INTENT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@
|
||||
<!ENTITY settings_title "Settings">
|
||||
<!ENTITY pref_category_advanced "Advanced">
|
||||
<!ENTITY pref_category_customize "Customize">
|
||||
<!ENTITY pref_category_search2 "Search settings">
|
||||
<!ENTITY pref_category_search3 "Search">
|
||||
<!ENTITY pref_category_display "Display">
|
||||
<!ENTITY pref_category_privacy_short "Privacy">
|
||||
<!ENTITY pref_category_vendor "&vendorShortName;">
|
||||
|
@ -9,18 +9,24 @@
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto"
|
||||
android:enabled="false">
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_home"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_home" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_search"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_search"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_home"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_home" />
|
||||
</PreferenceScreen>
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
@ -32,13 +38,6 @@
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
android:persistent="false" />
|
||||
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
<ListPreference android:key="app.update.autodownload"
|
||||
android:title="@string/pref_update_autodownload"
|
||||
android:entries="@array/pref_update_autodownload_entries"
|
||||
|
@ -16,17 +16,24 @@
|
||||
android:title="@string/pref_sync"
|
||||
android:persistent="false" />
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_home"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_home" />
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_search"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_search"/>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_home"
|
||||
android:fragment="org.mozilla.gecko.preferences.GeckoPreferenceFragment" >
|
||||
<extra android:name="resource"
|
||||
android:value="preferences_home" />
|
||||
</PreferenceScreen>
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
@ -38,13 +45,6 @@
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
android:persistent="false" />
|
||||
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
<ListPreference android:key="app.update.autodownload"
|
||||
android:title="@string/pref_update_autodownload"
|
||||
android:entries="@array/pref_update_autodownload_entries"
|
||||
|
@ -7,16 +7,6 @@
|
||||
xmlns:gecko="http://schemas.android.com/apk/res-auto"
|
||||
android:enabled="false">
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_search" >
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:targetPackage="@string/android_package_name"
|
||||
android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
|
||||
<extra
|
||||
android:name="resource"
|
||||
android:value="preferences_search" />
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_home" >
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:targetPackage="@string/android_package_name"
|
||||
@ -27,6 +17,24 @@
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_category_search" >
|
||||
<intent android:action="android.intent.action.VIEW"
|
||||
android:targetPackage="@string/android_package_name"
|
||||
android:targetClass="org.mozilla.gecko.preferences.GeckoPreferences" >
|
||||
<extra
|
||||
android:name="resource"
|
||||
android:value="preferences_search" />
|
||||
</intent>
|
||||
</PreferenceScreen>
|
||||
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
gecko:entries="@array/pref_import_android_entries"
|
||||
@ -37,12 +45,6 @@
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
android:persistent="false" />
|
||||
|
||||
<ListPreference android:key="android.not_a_preference.restoreSession3"
|
||||
android:title="@string/pref_restore"
|
||||
android:defaultValue="quit"
|
||||
android:entries="@array/pref_restore_entries"
|
||||
android:entryValues="@array/pref_restore_values"
|
||||
android:persistent="true" />
|
||||
|
||||
<ListPreference android:key="app.update.autodownload"
|
||||
android:title="@string/pref_update_autodownload"
|
||||
|
@ -93,7 +93,7 @@
|
||||
<string name="settings_title">&settings_title;</string>
|
||||
<string name="pref_category_advanced">&pref_category_advanced;</string>
|
||||
<string name="pref_category_customize">&pref_category_customize;</string>
|
||||
<string name="pref_category_search">&pref_category_search2;</string>
|
||||
<string name="pref_category_search">&pref_category_search3;</string>
|
||||
<string name="pref_category_display">&pref_category_display;</string>
|
||||
<string name="pref_category_privacy_short">&pref_category_privacy_short;</string>
|
||||
<string name="pref_category_vendor">&pref_category_vendor;</string>
|
||||
|
@ -31,10 +31,10 @@ public class testSettingsMenuItems extends PixelTest {
|
||||
|
||||
// Customize menu items.
|
||||
String[][] OPTIONS_CUSTOMIZE = {
|
||||
{ "Search settings", "", "Show search suggestions", "Installed search engines"},
|
||||
{ "Home", "", "Panels" },
|
||||
{ "Import from Android", "", "Bookmarks", "History", "Import" },
|
||||
{ "Search", "", "Show search suggestions", "Installed search engines"},
|
||||
{ "Tabs", "Don't restore after quitting " + BRAND_NAME, "Always restore", "Don't restore after quitting " + BRAND_NAME },
|
||||
{ "Import from Android", "", "Bookmarks", "History", "Import" },
|
||||
};
|
||||
|
||||
// Display menu items.
|
||||
|
@ -194,7 +194,11 @@ HawkClient.prototype = {
|
||||
};
|
||||
|
||||
let request = new HAWKAuthenticatedRESTRequest(uri, credentials, extra);
|
||||
request[method](payloadObj, onComplete);
|
||||
if (method == "post" || method == "put") {
|
||||
request[method](payloadObj, onComplete);
|
||||
} else {
|
||||
request[method](onComplete);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
@ -763,19 +763,25 @@ HAWKAuthenticatedRESTRequest.prototype = {
|
||||
__proto__: RESTRequest.prototype,
|
||||
|
||||
dispatch: function dispatch(method, data, onComplete, onProgress) {
|
||||
let contentType = "text/plain";
|
||||
if (method == "POST" || method == "PUT") {
|
||||
contentType = "application/json";
|
||||
}
|
||||
if (this.credentials) {
|
||||
let options = {
|
||||
now: this.now,
|
||||
localtimeOffsetMsec: this.localtimeOffsetMsec,
|
||||
credentials: this.credentials,
|
||||
payload: data && JSON.stringify(data) || "",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
contentType: contentType,
|
||||
};
|
||||
let header = CryptoUtils.computeHAWK(this.uri, method, options);
|
||||
this.setHeader("Authorization", header.field);
|
||||
this._log.trace("hawk auth header: " + header.field);
|
||||
}
|
||||
|
||||
this.setHeader("Content-Type", contentType);
|
||||
|
||||
return RESTRequest.prototype.dispatch.call(
|
||||
this, method, data, onComplete, onProgress
|
||||
);
|
||||
|
@ -178,7 +178,6 @@ function uninstallFakePAC() {
|
||||
// to ensure that still works.
|
||||
function setDefaultIdentityConfig() {
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Services.prefs.setBoolPref("identity.fxaccounts.enabled", false);
|
||||
// Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", false);
|
||||
Services.prefs.setBoolPref("services.sync.fxaccounts.enabled", false);
|
||||
}
|
||||
setDefaultIdentityConfig();
|
||||
|
@ -385,15 +385,6 @@ InternalMethods.prototype = {
|
||||
Services.obs.notifyObservers(null, topic, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Give xpcshell tests an override point for duration testing. This is
|
||||
* necessary because the tests need to manipulate the date in order to
|
||||
* simulate certificate expiration.
|
||||
*/
|
||||
now: function() {
|
||||
return Date.now();
|
||||
},
|
||||
|
||||
pollEmailStatus: function pollEmailStatus(sessionToken, why) {
|
||||
let myGenerationCount = this.generationCount;
|
||||
log.debug("entering pollEmailStatus: " + why + " " + myGenerationCount);
|
||||
@ -489,6 +480,20 @@ this.FxAccounts = function(mockInternal) {
|
||||
this.FxAccounts.prototype = Object.freeze({
|
||||
version: DATA_FORMAT_VERSION,
|
||||
|
||||
now: function() {
|
||||
if (this.internal) {
|
||||
return this.internal.now();
|
||||
}
|
||||
return internal.now();
|
||||
},
|
||||
|
||||
get localtimeOffsetMsec() {
|
||||
if (this.internal) {
|
||||
return this.internal.localtimeOffsetMsec;
|
||||
}
|
||||
return internal.localtimeOffsetMsec;
|
||||
},
|
||||
|
||||
// set() makes sure that polling is happening, if necessary.
|
||||
// get() does not wait for verification, and returns an object even if
|
||||
// unverified. The caller of get() must check .verified .
|
||||
@ -620,7 +625,6 @@ this.FxAccounts.prototype = Object.freeze({
|
||||
return internal.whenVerified(userData);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Sign the current user out.
|
||||
*
|
||||
@ -638,7 +642,26 @@ this.FxAccounts.prototype = Object.freeze({
|
||||
throw new Error("Firefox Accounts server must use HTTPS");
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
// Returns a promise that resolves with the URL to use to force a re-signin
|
||||
// of the current account.
|
||||
promiseAccountsForceSigninURI: function() {
|
||||
let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.force_auth.uri");
|
||||
if (!/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting
|
||||
throw new Error("Firefox Accounts server must use HTTPS");
|
||||
}
|
||||
// but we need to append the email address onto a query string.
|
||||
return this.getSignedInUser().then(accountData => {
|
||||
if (!accountData) {
|
||||
return null;
|
||||
}
|
||||
let newQueryPortion = url.indexOf("?") == -1 ? "?" : "&";
|
||||
newQueryPortion += "email=" + encodeURIComponent(accountData.email);
|
||||
return url + newQueryPortion;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -66,24 +66,6 @@ WeaveService.prototype = {
|
||||
},
|
||||
|
||||
get fxAccountsEnabled() {
|
||||
// first check if Firefox accounts is available at all. This is so we can
|
||||
// get this landed without forcing Fxa to be used (and require nightly
|
||||
// testers to manually set this pref)
|
||||
// Once we decide we want Fxa to be available, we just remove this block
|
||||
// (although a fly in this ointment is tests - it might be that we must
|
||||
// just set this as a pref with a default of true)
|
||||
let fxAccountsAvailable;
|
||||
try {
|
||||
fxAccountsAvailable = Services.prefs.getBoolPref("identity.fxaccounts.enabled");
|
||||
} catch (_) {
|
||||
}
|
||||
if (!fxAccountsAvailable) {
|
||||
// Currently we don't support toggling this pref after initialization, so
|
||||
// inject the pref value as a regular boolean.
|
||||
delete this.fxAccountsEnabled;
|
||||
this.fxAccountsEnabled = false;
|
||||
return false;
|
||||
}
|
||||
// work out what identity manager to use. This is stored in a preference;
|
||||
// if the preference exists, we trust it.
|
||||
let fxAccountsEnabled;
|
||||
|
@ -46,6 +46,15 @@ function deriveKeyBundle(kB) {
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/*
|
||||
General authentication error for abstracting authentication
|
||||
errors from multiple sources (e.g., from FxAccounts, TokenServer)
|
||||
'message' is a string with a description of the error
|
||||
*/
|
||||
function AuthenticationError(message) {
|
||||
this.message = message || "";
|
||||
}
|
||||
|
||||
this.BrowserIDManager = function BrowserIDManager() {
|
||||
this._fxaService = fxAccounts;
|
||||
this._tokenServerClient = new TokenServerClient();
|
||||
@ -86,6 +95,7 @@ this.BrowserIDManager.prototype = {
|
||||
initialize: function() {
|
||||
Services.obs.addObserver(this, fxAccountsCommon.ONLOGIN_NOTIFICATION, false);
|
||||
Services.obs.addObserver(this, fxAccountsCommon.ONLOGOUT_NOTIFICATION, false);
|
||||
Services.obs.addObserver(this, "weave:service:logout:finish", false);
|
||||
return this.initializeWithCurrentIdentity();
|
||||
},
|
||||
|
||||
@ -145,8 +155,7 @@ this.BrowserIDManager.prototype = {
|
||||
this._shouldHaveSyncKeyBundle = true; // but we probably don't have one...
|
||||
this.whenReadyToAuthenticate.reject(err);
|
||||
// report what failed...
|
||||
this._log.error("Background fetch for key bundle failed: " + err);
|
||||
throw err;
|
||||
this._log.error("Background fetch for key bundle failed: " + err.message);
|
||||
});
|
||||
// and we are done - the fetch continues on in the background...
|
||||
}).then(null, err => {
|
||||
@ -168,6 +177,14 @@ this.BrowserIDManager.prototype = {
|
||||
this._account = null;
|
||||
Weave.Service.logout();
|
||||
break;
|
||||
|
||||
case "weave:service:logout:finish":
|
||||
// This signals an auth error with the storage server,
|
||||
// or that the user unlinked her account from the browser.
|
||||
// Either way, we clear our auth token. In the case of an
|
||||
// auth error, this will force the fetch of a new one.
|
||||
this._token = null;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -194,11 +211,11 @@ this.BrowserIDManager.prototype = {
|
||||
* Provide override point for testing token expiration.
|
||||
*/
|
||||
_now: function() {
|
||||
return this._fxaService.internal.now()
|
||||
return this._fxaService.now()
|
||||
},
|
||||
|
||||
get _localtimeOffsetMsec() {
|
||||
return this._fxaService.internal.localtimeOffsetMsec;
|
||||
return this._fxaService.localtimeOffsetMsec;
|
||||
},
|
||||
|
||||
get account() {
|
||||
@ -364,10 +381,12 @@ this.BrowserIDManager.prototype = {
|
||||
_fetchSyncKeyBundle: function() {
|
||||
// Fetch a sync token for the logged in user from the token server.
|
||||
return this._fxaService.getKeys().then(userData => {
|
||||
// unlikely, but if the logged in user somehow changed between these
|
||||
// calls we better fail.
|
||||
if (!userData || userData.email !== this.account) {
|
||||
throw new Error("The currently logged-in user has changed.");
|
||||
// Unlikely, but if the logged in user somehow changed between these
|
||||
// calls we better fail. TODO: add tests for these
|
||||
if (!userData) {
|
||||
throw new AuthenticationError("No userData in _fetchSyncKeyBundle");
|
||||
} else if (userData.email !== this.account) {
|
||||
throw new AuthenticationError("Unexpected user change in _fetchSyncKeyBundle");
|
||||
}
|
||||
return this._fetchTokenForUser(userData).then(token => {
|
||||
this._token = token;
|
||||
@ -397,7 +416,7 @@ this.BrowserIDManager.prototype = {
|
||||
let cb = function (err, token) {
|
||||
if (err) {
|
||||
log.info("TokenServerClient.getTokenFromBrowserIDAssertion() failed with: " + err.message);
|
||||
return deferred.reject(err);
|
||||
return deferred.reject(new AuthenticationError(err.message));
|
||||
} else {
|
||||
return deferred.resolve(token);
|
||||
}
|
||||
@ -407,19 +426,44 @@ this.BrowserIDManager.prototype = {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
let audience = Services.io.newURI(tokenServerURI, null, null).prePath;
|
||||
function getAssertion() {
|
||||
let audience = Services.io.newURI(tokenServerURI, null, null).prePath;
|
||||
return fxAccounts.getAssertion(audience).then(null, err => {
|
||||
if (err.code === 401) {
|
||||
throw new AuthenticationError("Unable to get assertion for user");
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// wait until the account email is verified and we know that
|
||||
// getAssertion() will return a real assertion (not null).
|
||||
return this._fxaService.whenVerified(userData)
|
||||
.then(() => this._fxaService.getAssertion(audience))
|
||||
.then(() => getAssertion())
|
||||
.then(assertion => getToken(tokenServerURI, assertion))
|
||||
.then(token => {
|
||||
token.expiration = this._now() + (token.duration * 1000);
|
||||
// TODO: Make it be only 80% of the duration, so refresh the token
|
||||
// before it actually expires. This is to avoid sync storage errors
|
||||
// otherwise, we get a nasty notification bar briefly. Bug 966568.
|
||||
token.expiration = this._now() + (token.duration * 1000) * 0.80;
|
||||
return token;
|
||||
})
|
||||
.then(null, err => {
|
||||
Cu.reportError("Failed to fetch token: " + err);
|
||||
// XXX - TODO - work out how to set sync to an error state.
|
||||
// TODO: write tests to make sure that different auth error cases are handled here
|
||||
// properly: auth error getting assertion, auth error getting token (invalid generation
|
||||
// and client-state error)
|
||||
if (err instanceof AuthenticationError) {
|
||||
this._log.error("Authentication error in _fetchTokenForUser: " + err.message);
|
||||
// Drop the sync key bundle, but still expect to have one.
|
||||
// This will arrange for us to be in the right 'currentAuthState'
|
||||
// such that UI will show the right error.
|
||||
this._shouldHaveSyncKeyBundle = true;
|
||||
this._syncKeyBundle = null;
|
||||
Weave.Status.login = this.currentAuthState;
|
||||
Services.obs.notifyObservers(null, "weave:service:login:error", null);
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -136,13 +136,21 @@ add_test(function test_resourceAuthenticatorSkew() {
|
||||
do_check_eq(fxa.internal.now(), now);
|
||||
do_check_eq(fxa.internal.localtimeOffsetMsec, localtimeOffsetMsec);
|
||||
|
||||
do_check_eq(fxa.now(), now);
|
||||
do_check_eq(fxa.localtimeOffsetMsec, localtimeOffsetMsec);
|
||||
|
||||
// Mocks within mocks...
|
||||
configureFxAccountIdentity(browseridManager, identityConfig);
|
||||
browseridManager._fxaService = fxa;
|
||||
|
||||
do_check_eq(browseridManager._fxaService.internal.now(), now);
|
||||
do_check_eq(browseridManager._fxaService.internal.localtimeOffsetMsec,
|
||||
localtimeOffsetMsec);
|
||||
|
||||
do_check_eq(browseridManager._fxaService.now(), now);
|
||||
do_check_eq(browseridManager._fxaService.localtimeOffsetMsec,
|
||||
localtimeOffsetMsec);
|
||||
|
||||
let request = new SyncStorageRequest("https://example.net/i/like/pie/");
|
||||
let authenticator = browseridManager.getResourceAuthenticator();
|
||||
let output = authenticator(request, 'GET');
|
||||
|
Loading…
x
Reference in New Issue
Block a user