Merge autoland to central, a=merge

MozReview-Commit-ID: FOw9Q98gVXH
This commit is contained in:
Wes Kocher 2017-08-15 18:51:25 -07:00
commit 5a4fb82b72
216 changed files with 2196 additions and 1470 deletions

View File

@ -8,6 +8,7 @@ support-files =
[test_aria_alert.html]
[test_aria_menu.html]
skip-if = stylo # bug 1390409
[test_aria_objattr.html]
[test_aria_owns.html]
[test_aria_statechange.html]
@ -20,6 +21,7 @@ support-files =
[test_contextmenu.html]
[test_descrchange.html]
[test_docload.html]
skip-if = stylo # bug 1390409
[test_docload_aria.html]
[test_dragndrop.html]
[test_flush.html]
@ -43,6 +45,7 @@ skip-if = os == 'win' || os == 'linux'
[test_label.xul]
[test_menu.xul]
[test_mutation.html]
skip-if = stylo # bug 1390409
[test_mutation.xhtml]
[test_namechange.xul]
[test_namechange.html]

View File

@ -39,4 +39,5 @@ skip-if = buildapp == "mulet"
[test_table.html]
[test_textleaf.html]
[test_visibility.html]
skip-if = stylo # bug 1390409
[test_whitespace.html]

View File

@ -1944,6 +1944,69 @@ var BookmarkingUI = {
PanelUI.hide();
},
showBookmarkingTools(triggerNode) {
const panelID = "PanelUI-bookmarkingTools";
let viewNode = document.getElementById(panelID);
for (let button of [...viewNode.getElementsByTagName("toolbarbutton")]) {
let update = true;
switch (button.id) {
case "panelMenu_toggleBookmarksMenu":
let placement = CustomizableUI.getPlacementOfWidget(this.BOOKMARK_BUTTON_ID);
button.setAttribute("checked", !!placement && placement.area == CustomizableUI.AREA_NAVBAR);
break;
case "panelMenu_viewBookmarksSidebar":
button.setAttribute("checked", SidebarUI.currentID == "viewBookmarksSidebar");
break;
default:
update = false;
break;
}
if (update) {
updateToggleControlLabel(button);
}
}
PanelUI.showSubView(panelID, triggerNode);
},
toggleMenuButtonInToolbar(triggerNode) {
let placement = CustomizableUI.getPlacementOfWidget(this.BOOKMARK_BUTTON_ID);
const area = CustomizableUI.AREA_NAVBAR;
if (!placement) {
// Button is in the palette, so we can move it to the navbar.
let pos;
let widgetIDs = CustomizableUI.getWidgetIdsInArea(CustomizableUI.AREA_NAVBAR);
// If there's a spring inside the navbar, find it and use that as the
// placement marker.
let lastSpringID = null;
for (let i = widgetIDs.length - 1; i >= 0; --i) {
let id = widgetIDs[i];
if (CustomizableUI.isSpecialWidget(id) && /spring/.test(id)) {
lastSpringID = id;
break;
}
}
if (lastSpringID) {
pos = CustomizableUI.getPlacementOfWidget(lastSpringID).position + 1;
} else {
// Next alternative is to use the searchbar as the placement marker.
const searchWidgetID = "search-container";
if (widgetIDs.includes(searchWidgetID)) {
pos = CustomizableUI.getPlacementOfWidget(searchWidgetID).position + 1;
} else {
// Last alternative is to use the navbar as the placement marker.
pos = CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1;
}
}
CustomizableUI.addWidgetToArea(this.BOOKMARK_BUTTON_ID, area, pos);
} else {
// Move it back to the palette.
CustomizableUI.removeWidgetFromArea(this.BOOKMARK_BUTTON_ID);
}
triggerNode.setAttribute("checked", !placement);
updateToggleControlLabel(triggerNode);
},
// nsINavBookmarkObserver
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle, aDateAdded, aGuid) {
if (aURI && aURI.equals(this._uri)) {

View File

@ -288,10 +288,12 @@ var SidebarUI = {
* with a different commandID, then the sidebar will be opened using the
* specified commandID. Otherwise the sidebar will be hidden.
*
* @param {string} commandID ID of the xul:broadcaster element to use.
* @param {string} commandID ID of the xul:broadcaster element to use.
* @param {DOMNode} [triggerNode] Node, usually a button, that triggered the
* visibility toggling of the sidebar.
* @return {Promise}
*/
toggle(commandID = this.lastOpenedId) {
toggle(commandID = this.lastOpenedId, triggerNode) {
// First priority for a default value is this.lastOpenedId which is set during show()
// and not reset in hide(), unlike currentID. If show() hasn't been called or the command
// doesn't exist anymore, then fallback to a default sidebar.
@ -300,10 +302,10 @@ var SidebarUI = {
}
if (this.isOpen && commandID == this.currentID) {
this.hide();
this.hide(triggerNode);
return Promise.resolve();
}
return this.show(commandID);
return this.show(commandID, triggerNode);
},
/**
@ -312,10 +314,15 @@ var SidebarUI = {
*
* This wraps the internal method, including a ping to telemetry.
*
* @param {string} commandID ID of the xul:broadcaster element to use.
* @param {string} commandID ID of the xul:broadcaster element to use.
* @param {DOMNode} [triggerNode] Node, usually a button, that triggered the
* showing of the sidebar.
*/
show(commandID) {
show(commandID, triggerNode) {
return this._show(commandID).then(() => {
if (triggerNode) {
updateToggleControlLabel(triggerNode);
}
BrowserUITelemetry.countSidebarEvent(commandID, "show");
});
},
@ -403,8 +410,11 @@ var SidebarUI = {
/**
* Hide the sidebar.
*
* @param {DOMNode} [triggerNode] Node, usually a button, that triggered the
* hiding of the sidebar.
*/
hide() {
hide(triggerNode) {
if (!this.isOpen) {
return;
}
@ -437,6 +447,9 @@ var SidebarUI = {
selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
{commandID, isOpen: false}
);
if (triggerNode) {
updateToggleControlLabel(triggerNode);
}
BrowserUITelemetry.countSidebarEvent(commandID, "hide");
},
};

View File

@ -5481,9 +5481,11 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
}
function onViewToolbarCommand(aEvent) {
var toolbarId = aEvent.originalTarget.getAttribute("toolbarId");
var isVisible = aEvent.originalTarget.getAttribute("checked") == "true";
let node = aEvent.originalTarget;
let toolbarId = node.getAttribute("toolbarId");
let isVisible = node.getAttribute("checked") == "true";
CustomizableUI.setToolbarVisibility(toolbarId, isVisible);
updateToggleControlLabel(node);
}
function setToolbarVisibility(toolbar, isVisible, persist = true) {
@ -5515,6 +5517,18 @@ function setToolbarVisibility(toolbar, isVisible, persist = true) {
BookmarkingUI.onToolbarVisibilityChange();
}
function updateToggleControlLabel(control) {
if (!control.hasAttribute("label-checked")) {
return;
}
if (!control.hasAttribute("label-unchecked")) {
control.setAttribute("label-unchecked", control.getAttribute("label"));
}
let prefix = (control.getAttribute("checked") == "true") ? "" : "un";
control.setAttribute("label", control.getAttribute(`label-${prefix}checked`));
}
var TabletModeUpdater = {
init() {
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {

View File

@ -446,6 +446,7 @@
type="arrow"
hidden="true"
flip="slide"
photon="true"
position="bottomcenter topright"
tabspecific="true"
noautofocus="true"

View File

@ -703,6 +703,12 @@ this.PanelMultiView = class {
return;
}
// If this instance was destructed in the meantime, there's no point in
// trying to show anything here.
if (!this.node) {
return;
}
this._currentSubView = viewNode;
viewNode.setAttribute("current", true);

View File

@ -234,13 +234,11 @@
observes="bookmarkThisPageBroadcaster"
command="Browser:AddBookmarkAs"
onclick="PanelUI.hide();"/>
<toolbarbutton id="panelMenu_viewBookmarksSidebar"
label="&viewBookmarksSidebar2.label;"
class="subviewbutton subviewbutton-iconic"
key="viewBookmarksSidebarKb"
oncommand="SidebarUI.toggle('viewBookmarksSidebar'); PanelUI.hide();">
<observes element="viewBookmarksSidebar" attribute="checked"/>
</toolbarbutton>
<toolbarbutton id="panelMenu_bookmarkingTools"
label="&bookmarkingTools.label;"
class="subviewbutton subviewbutton-iconic subviewbutton-nav"
closemenu="none"
oncommand="BookmarkingUI.showBookmarkingTools(this);"/>
<toolbarbutton id="panelMenu_searchBookmarks"
label="&searchBookmarks.label;"
class="subviewbutton subviewbutton-iconic"
@ -351,6 +349,7 @@
type="arrow"
noautofocus="true"
position="bottomcenter topright"
photon="true"
hidden="true">
<photonpanelmultiview mainViewId="widget-overflow-mainView">
<panelview id="widget-overflow-mainView"
@ -736,5 +735,31 @@
oncommand="PanelUI.showSubView('PanelUI-remotetabs', this)"/>
</vbox>
</panelview>
<panelview id="PanelUI-bookmarkingTools" class="PanelUI-subView">
<vbox class="panel-subview-body">
<toolbarbutton id="panelMenu_toggleBookmarksMenu"
label="&addBookmarksMenu.label;"
label-checked="&removeBookmarksMenu.label;"
class="subviewbutton subviewbutton-iconic"
oncommand="BookmarkingUI.toggleMenuButtonInToolbar(this); PanelUI.hide();"/>
<toolbarbutton id="panelMenu_viewBookmarksSidebar"
label="&viewBookmarksSidebar2.label;"
label-checked="&hideBookmarksSidebar.label;"
class="subviewbutton subviewbutton-iconic"
key="viewBookmarksSidebarKb"
oncommand="SidebarUI.toggle('viewBookmarksSidebar', this); PanelUI.hide();">
<observes element="viewBookmarksSidebar" attribute="checked"/>
</toolbarbutton>
<toolbarbutton id="panelMenu_viewBookmarksToolbar"
class="subviewbutton subviewbutton-iconic"
placesanonid="view-toolbar"
toolbarId="PersonalToolbar"
type="checkbox"
oncommand="onViewToolbarCommand(event)"
label="&viewBookmarksToolbar.label;"
label-checked="&hideBookmarksToolbar.label;"/>
</vbox>
</panelview>
</photonpanelmultiview>
</panel>

View File

@ -948,7 +948,6 @@ var gMainPane = {
let rv = Services.prompt.confirmEx(window, title, message, buttonFlags,
okButton, cancelButton, null, null, {});
if (rv == 0) {
ContextualIdentityService.closeContainerTabs();
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}

View File

@ -87,7 +87,6 @@ var gPrivacyPane = {
let count = ContextualIdentityService.countContainerTabs();
if (count == 0) {
ContextualIdentityService.notifyAllContainersCleared();
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
return;
}
@ -108,9 +107,6 @@ var gPrivacyPane = {
okButton, cancelButton, null, null, {});
if (rv == 0) {
Services.prefs.setBoolPref("privacy.userContext.enabled", false);
ContextualIdentityService.closeContainerTabs().then(() => {
ContextualIdentityService.notifyAllContainersCleared();
});
return;
}

View File

@ -835,8 +835,8 @@ this.UITour = {
node: aWindow.PanelUI.panel,
events: [
[ "popuphidden", this.onPanelHidden ],
[ "popuphiding", this.hideAppMenuAnnotations ],
[ "ViewShowing", this.hideAppMenuAnnotations ]
[ "popuphiding", this.onAppMenuHiding ],
[ "ViewShowing", this.onAppMenuSubviewShowing ]
]
},
{
@ -844,8 +844,8 @@ this.UITour = {
node: aWindow.BrowserPageActions.panelNode,
events: [
[ "popuphidden", this.onPanelHidden ],
[ "popuphiding", this.hidePageActionPanelAnnotations ],
[ "ViewShowing", this.hidePageActionPanelAnnotations ]
[ "popuphiding", this.onPageActionPanelHiding ],
[ "ViewShowing", this.onPageActionPanelSubviewShowing ]
]
},
{
@ -853,7 +853,7 @@ this.UITour = {
node: aWindow.gIdentityHandler._identityPopup,
events: [
[ "popuphidden", this.onPanelHidden ],
[ "popuphiding", this.hideControlCenterAnnotations ]
[ "popuphiding", this.onControlCenterHiding ]
]
},
];
@ -1125,7 +1125,7 @@ this.UITour = {
* @see UITour.highlightEffects
*/
async showHighlight(aChromeWindow, aTarget, aEffect = "none") {
let showHighlightPanel = (aAnchorEl) => {
let showHighlightElement = (aAnchorEl) => {
let highlighter = aChromeWindow.document.getElementById("UITourHighlight");
let effect = aEffect;
@ -1185,17 +1185,21 @@ this.UITour = {
try {
await this._ensureTarget(aChromeWindow, aTarget);
let anchorEl = await this._correctAnchor(aChromeWindow, aTarget);
showHighlightPanel(anchorEl);
showHighlightElement(anchorEl);
} catch (e) {
log.warn(e);
}
},
hideHighlight(aWindow) {
_hideHighlightElement(aWindow) {
let highlighter = aWindow.document.getElementById("UITourHighlight");
this._removeAnnotationPanelMutationObserver(highlighter.parentElement);
highlighter.parentElement.hidePopup();
highlighter.removeAttribute("active");
},
hideHighlight(aWindow) {
this._hideHighlightElement(aWindow);
this._setMenuStateForAnnotation(aWindow, false, "appMenu");
this._setMenuStateForAnnotation(aWindow, false, "pageActionPanel");
},
@ -1215,7 +1219,7 @@ this.UITour = {
*/
async showInfo(aChromeWindow, aAnchor, aTitle = "", aDescription = "",
aIconURL = "", aButtons = [], aOptions = {}) {
let showInfoPanel = (aAnchorEl) => {
let showInfoElement = (aAnchorEl) => {
aAnchorEl.focus();
let document = aChromeWindow.document;
@ -1314,7 +1318,7 @@ this.UITour = {
try {
await this._ensureTarget(aChromeWindow, aAnchor);
let anchorEl = await this._correctAnchor(aChromeWindow, aAnchor);
showInfoPanel(anchorEl);
showInfoElement(anchorEl);
} catch (e) {
log.warn(e);
}
@ -1326,19 +1330,22 @@ this.UITour = {
return tooltip.getAttribute("targetName") == aTargetName && tooltip.state != "closed";
},
hideInfo(aWindow) {
_hideInfoElement(aWindow) {
let document = aWindow.document;
let tooltip = document.getElementById("UITourTooltip");
this._removeAnnotationPanelMutationObserver(tooltip);
tooltip.hidePopup();
this._setMenuStateForAnnotation(aWindow, false, "appMenu");
this._setMenuStateForAnnotation(aWindow, false, "pageActionPanel");
let tooltipButtons = document.getElementById("UITourTooltipButtons");
while (tooltipButtons.firstChild)
tooltipButtons.firstChild.remove();
},
hideInfo(aWindow) {
this._hideInfoElement(aWindow);
this._setMenuStateForAnnotation(aWindow, false, "appMenu");
this._setMenuStateForAnnotation(aWindow, false, "pageActionPanel");
},
showMenu(aWindow, aMenuName, aOpenCallback = null) {
log.debug("showMenu:", aMenuName);
function openMenuButton(aMenuBtn) {
@ -1358,11 +1365,13 @@ this.UITour = {
};
if (aMenuName == "appMenu") {
menu.node = aWindow.PanelUI.panel;
menu.hideMenuAnnotations = this.hideAppMenuAnnotations;
menu.onPopupHiding = this.onAppMenuHiding;
menu.onViewShowing = this.onAppMenuSubviewShowing;
menu.show = () => aWindow.PanelUI.show();
} else {
menu.node = aWindow.BrowserPageActions.panelNode;
menu.hideMenuAnnotations = this.hidePageActionPanelAnnotations;
menu.onPopupHiding = this.onPageActionPanelHiding;
menu.onViewShowing = this.onPageActionPanelSubviewShowing;
menu.show = () => aWindow.BrowserPageActions.showPanel();
}
@ -1375,8 +1384,8 @@ this.UITour = {
menu.node.addEventListener("popupshown", aOpenCallback, { once: true });
}
menu.node.addEventListener("popuphidden", menu.onPanelHidden);
menu.node.addEventListener("popuphiding", menu.hideMenuAnnotations);
menu.node.addEventListener("ViewShowing", menu.hideMenuAnnotations);
menu.node.addEventListener("popuphiding", menu.onPopupHiding);
menu.node.addEventListener("ViewShowing", menu.onViewShowing);
menu.show();
} else if (aMenuName == "bookmarks") {
let menuBtn = aWindow.document.getElementById("bookmarks-menu-button");
@ -1386,7 +1395,7 @@ this.UITour = {
// Add the listener even if the panel is already open since it will still
// only get registered once even if it was UITour that opened it.
popup.addEventListener("popuphiding", this.hideControlCenterAnnotations);
popup.addEventListener("popuphiding", this.onControlCenterHiding);
popup.addEventListener("popuphidden", this.onPanelHidden);
popup.setAttribute("noautohide", "true");
@ -1491,12 +1500,22 @@ this.UITour = {
aWindow.openLinkIn("about:newtab", "current", {targetBrowser: aBrowser});
},
_hideAnnotationsForPanel(aEvent, aTargetPositionCallback) {
_hideAnnotationsForPanel(aEvent, aShouldClosePanel, aTargetPositionCallback) {
let win = aEvent.target.ownerGlobal;
let hideHighlightMethod = null;
let hideInfoMethod = null;
if (aShouldClosePanel) {
hideHighlightMethod = aWin => this.hideHighlight(aWin);
hideInfoMethod = aWin => this.hideInfo(aWin);
} else {
// Don't have to close panel, let's only hide annotation elements
hideHighlightMethod = aWin => this._hideHighlightElement(aWin);
hideInfoMethod = aWin => this._hideInfoElement(aWin);
}
let annotationElements = new Map([
// [annotationElement (panel), method to hide the annotation]
[win.document.getElementById("UITourHighlightContainer"), UITour.hideHighlight.bind(UITour)],
[win.document.getElementById("UITourTooltip"), UITour.hideInfo.bind(UITour)],
[win.document.getElementById("UITourHighlightContainer"), hideHighlightMethod],
[win.document.getElementById("UITourTooltip"), hideInfoMethod],
]);
annotationElements.forEach((hideMethod, annotationElement) => {
if (annotationElement.state != "closed") {
@ -1515,16 +1534,24 @@ this.UITour = {
});
},
hideAppMenuAnnotations(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, UITour.targetIsInAppMenu);
onAppMenuHiding(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, true, UITour.targetIsInAppMenu);
},
hidePageActionPanelAnnotations(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, UITour.targetIsInPageActionPanel);
onAppMenuSubviewShowing(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, false, UITour.targetIsInAppMenu);
},
hideControlCenterAnnotations(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, (aTarget) => {
onPageActionPanelHiding(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, true, UITour.targetIsInPageActionPanel);
},
onPageActionPanelSubviewShowing(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, false, UITour.targetIsInPageActionPanel);
},
onControlCenterHiding(aEvent) {
UITour._hideAnnotationsForPanel(aEvent, true, (aTarget) => {
return aTarget.targetName.startsWith("controlCenter-");
});
},

View File

@ -28,6 +28,7 @@ skip-if = os == "linux" # Intermittent failures, bug 951965
[browser_UITour2.js]
[browser_UITour3.js]
[browser_UITour4.js]
[browser_UITour5.js]
skip-if = os == "linux" # Linux: Bug 986760, Bug 989101.
[browser_UITour_availableTargets.js]
[browser_UITour_annotation_size_attributes.js]

View File

@ -0,0 +1,41 @@
"use strict";
var gTestTab;
var gContentAPI;
var gContentWindow;
add_task(setup_UITourTest);
add_UITour_task(async function test_highlight_library_and_show_library_subview() {
let highlight = document.getElementById("UITourHighlight");
is_element_hidden(highlight, "Highlight should initially be hidden");
// Test highlighting the library button
let appMenu = PanelUI.panel;
let appMenuShownPromise = promisePanelElementShown(window, appMenu);
let highlightVisiblePromise = elementVisiblePromise(highlight, "Should show highlight");
gContentAPI.showHighlight("library");
await appMenuShownPromise;
await highlightVisiblePromise;
is(appMenu.state, "open", "Should open the app menu to highlight the library button");
is(getShowHighlightTargetName(), "library", "Should highlight the library button on the app menu");
// Click the library button to show the subview
let ViewShownPromise = new Promise(resolve => {
appMenu.addEventListener("ViewShown", resolve, { once: true });
});
let highlightHiddenPromise = elementHiddenPromise(highlight, "Should hide highlight");
let libraryBtn = document.getElementById("appMenu-library-button");
libraryBtn.dispatchEvent(new Event("command"));
await highlightHiddenPromise;
await ViewShownPromise;
is(PanelUI.multiView.current.id, "appMenu-libraryView", "Should show the library subview");
is(appMenu.state, "open", "Should still open the app menu for the library subview");
// Clean up
let appMenuHiddenPromise = promisePanelElementHidden(window, appMenu);
gContentAPI.hideMenu("appMenu");
await appMenuHiddenPromise;
is(appMenu.state, "closed", "Should close the app menu");
});

View File

@ -34,8 +34,6 @@ class ProfileAutoCompleteResult {
this.searchString = searchString;
// The field name of the focused input.
this._focusedFieldName = focusedFieldName;
// All field names in the form which contains the focused input.
this._allFieldNames = allFieldNames;
// The matching profiles contains the information for filling forms.
this._matchingProfiles = matchingProfiles;
// The default item that should be entered if none is selected
@ -44,6 +42,14 @@ class ProfileAutoCompleteResult {
this.errorDescription = "";
// The value used to determine whether the form is secure or not.
this._isSecure = isSecure;
// All fillable field names in the form including the field name of the currently-focused input.
this._allFieldNames = [...this._matchingProfiles.reduce((fieldSet, curProfile) => {
for (let field of Object.keys(curProfile)) {
fieldSet.add(field);
}
return fieldSet;
}, new Set())].filter(field => allFieldNames.includes(field));
// The result code of this result object.
if (resultCode) {

View File

@ -174,57 +174,41 @@
);
/**
* Update the text on the footer.
* A handler for updating warning message once selectedIndex has been changed.
*
* There're three different states of warning message:
* 1. None of addresses were selected: We show all the categories intersection of fields in the
* form and fields in the results.
* 2. An address was selested: Show the additional categories that will also be filled.
* 3. An address was selected, but the focused category is the same as the only one category: Only show
* the exact category that we're going to fill in.
*
* @private
* @param {string|string[]} categories
* A list of categories that used to generate the message.
* @param {boolean} hasExtraCategories
* Used to determine if it has the extra categories other than the focued category. If
* the value is true, we show "Also fill ...", otherwise, show "Fill ..." only.
* @param {string[]} data.categories
* The categories of all the fields contained in the selected address.
*/
const namespace = "category.";
this._updateText = (categories = this._allFieldCategories, hasExtraCategories = true) => {
let warningTextTmplKey = hasExtraCategories ? "phishingWarningMessage" : "phishingWarningMessage2";
let sep = this._stringBundle.GetStringFromName("fieldNameSeparator");
this._updateWarningNote = ({data} = {}) => {
let categories = (data && data.categories) ? data.categories : this._allFieldCategories;
// If the length of categories is 1, that means all the fillable fields are in the same
// category. We will change the way to inform user according to this flag. When the value
// is true, we show "Also autofills ...", otherwise, show "Autofills ..." only.
let hasExtraCategories = categories.length > 1;
// Show the categories in certain order to conform with the spec.
let orderedCategoryList = ["address", "name", "organization", "tel", "email"];
let showCategories = hasExtraCategories ?
orderedCategoryList.filter(category => categories.includes(category) && category != this._focusedCategory) :
[this._focusedCategory];
let categoriesText = showCategories.map(category => this._stringBundle.GetStringFromName(namespace + category)).join(sep);
let separator = this._stringBundle.GetStringFromName("fieldNameSeparator");
let warningTextTmplKey = hasExtraCategories ? "phishingWarningMessage" : "phishingWarningMessage2";
let categoriesText = showCategories.map(category => this._stringBundle.GetStringFromName(namespace + category)).join(separator);
this._warningTextBox.textContent = this._stringBundle.formatStringFromName(warningTextTmplKey,
[categoriesText], 1);
this.parentNode.parentNode.adjustHeight();
};
/**
* A handler for updating warning message once selectedIndex has been changed.
*
* There're three different states of warning message:
* 1. None of addresses were selected: We show all the categories in the form.
* 2. An address was selested: Show the additional categories that will also be filled.
* 3. An address was selected, but the focused category is the same as the only all categories: Only show
* the exact category that we're going to fill in.
*
* @private
* @param {string[]} categories
* The categories of all the fields contained in the selected address.
*/
this._updateWarningMsgHandler = ({data: {categories}} = {data: {}}) => {
let hasSelectedAddress = this._focusedCategory && categories;
// If the length of categories is 1, that means all the fillable fields are in the same
// category. We will change the way to inform user according to this flag.
let hasExtraCategories = hasSelectedAddress && categories.length > 1;
if (!hasSelectedAddress) {
this._updateText();
return;
}
this._updateText(categories, hasExtraCategories);
};
this._adjustAcItem();
]]>
</constructor>
@ -235,7 +219,7 @@
/* global messageManager */
if (this.showWarningText) {
messageManager.removeMessageListener("FormAutofill:UpdateWarningMessage", this._updateWarningMsgHandler);
messageManager.removeMessageListener("FormAutofill:UpdateWarningMessage", this._updateWarningNote);
}
this._itemBox.removeAttribute("no-warning");
@ -268,9 +252,9 @@
this.showWarningText = this._allFieldCategories && this._focusedCategory;
if (this.showWarningText) {
messageManager.addMessageListener("FormAutofill:UpdateWarningMessage", this._updateWarningMsgHandler);
messageManager.addMessageListener("FormAutofill:UpdateWarningMessage", this._updateWarningNote);
this._updateText();
this._updateWarningNote();
} else {
this._itemBox.setAttribute("no-warning", "true");
}

View File

@ -14,9 +14,10 @@ async function expectWarningText(browser, expectedText) {
}
add_task(async function setup_storage() {
await saveAddress(TEST_ADDRESS_1);
await saveAddress(TEST_ADDRESS_2);
await saveAddress(TEST_ADDRESS_3);
await saveAddress(TEST_ADDRESS_4);
await saveAddress(TEST_ADDRESS_5);
});
add_task(async function test_click_on_footer() {
@ -54,21 +55,32 @@ add_task(async function test_press_enter_on_footer() {
});
});
add_task(async function test_phishing_warning() {
add_task(async function test_phishing_warning_single_category() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
const {autoCompletePopup: {richlistbox: itemsBox}} = browser;
await openPopupOn(browser, "#street-address");
await openPopupOn(browser, "#tel");
const warningBox = itemsBox.querySelector(".autocomplete-richlistitem:last-child")._warningTextBox;
ok(warningBox, "Got phishing warning box");
await expectWarningText(browser, "Also autofills company, phone, email");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Also autofills company, phone, email");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Autofills address");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Also autofills company, phone, email");
await expectWarningText(browser, "Autofills phone");
await closePopup(browser);
});
});
add_task(async function test_phishing_warning_complex_categories() {
await BrowserTestUtils.withNewTab({gBrowser, url: URL}, async function(browser) {
await openPopupOn(browser, "#street-address");
await expectWarningText(browser, "Also autofills company, email");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Autofills address");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Also autofills company, email");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
await expectWarningText(browser, "Also autofills company, email");
await closePopup(browser);
});

View File

@ -1,5 +1,5 @@
/* exported MANAGE_ADDRESSES_DIALOG_URL, EDIT_ADDRESS_DIALOG_URL, BASE_URL,
TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3,
TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5,
TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3,
sleep, expectPopupOpen, openPopupOn, expectPopupClose, closePopup, clickDoorhangerButton,
getAddresses, saveAddress, removeAddresses, saveCreditCard,
@ -35,6 +35,19 @@ const TEST_ADDRESS_3 = {
"postal-code": "12345",
};
const TEST_ADDRESS_4 = {
"given-name": "Timothy",
"family-name": "Berners-Lee",
organization: "World Wide Web Consortium",
"street-address": "32 Vassar Street\nMIT Room 32-G524",
country: "US",
email: "timbl@w3.org",
};
const TEST_ADDRESS_5 = {
tel: "+16172535702",
};
const TEST_CREDIT_CARD_1 = {
"cc-name": "John Doe",
"cc-number": "1234567812345678",

View File

@ -244,11 +244,16 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY bookmarksCmd.commandkey "b">
<!ENTITY bookmarksMenuButton.label "Bookmarks">
<!ENTITY bookmarksMenuButton.other.label "Other Bookmarks">
<!ENTITY bookmarksMenuButton.mobile.label "Mobile Bookmarks">
<!ENTITY bookmarksMenuButton.other.label "Other Bookmarks">
<!ENTITY bookmarksMenuButton.mobile.label "Mobile Bookmarks">
<!ENTITY viewBookmarksSidebar2.label "View Bookmarks Sidebar">
<!ENTITY hideBookmarksSidebar.label "Hide Bookmarks Sidebar">
<!ENTITY viewBookmarksToolbar.label "View Bookmarks Toolbar">
<!ENTITY hideBookmarksToolbar.label "Hide Bookmarks Toolbar">
<!ENTITY searchBookmarks.label "Search Bookmarks">
<!ENTITY bookmarkingTools.label "Bookmarking Tools">
<!ENTITY addBookmarksMenu.label "Add Bookmarks Menu to Toolbar">
<!ENTITY removeBookmarksMenu.label "Remove Bookmarks Menu from Toolbar">
<!ENTITY containersMenu.label "Containers">

View File

@ -263,6 +263,7 @@ removeContainerOkButton=Remove this Container
removeContainerButton2=Dont remove this Container
# Search Input
# LOCALIZATION NOTE: Please keep the placeholder string shorter than around 30 characters to avoid truncation.
searchInput.labelWin=Find in Options
searchInput.labelUnix=Find in Preferences

View File

@ -396,7 +396,7 @@ html|*.addon-webext-perm-list {
}
.addon-addon-icon {
list-style-image: url("chrome://browser/skin/addons.svg");
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.svg");
}
.addon-toolbar-icon {

View File

@ -1359,7 +1359,7 @@ html|*.addon-webext-perm-list {
}
.addon-addon-icon {
list-style-image: url("chrome://browser/skin/addons.svg");
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.svg");
}
.addon-toolbar-icon {

View File

@ -63,3 +63,8 @@ body {
margin-top: 1.2em;
text-align: end;
}
#advisory_provider {
color: white;
text-decoration: underline;
}

View File

@ -257,7 +257,6 @@ photonpanelmultiview .panel-subview-header {
}
#appMenu-popup > .panel-arrowcontainer > .panel-arrowcontent,
#PanelUI-popup > .panel-arrowcontainer > .panel-arrowcontent,
panel[photon] > .panel-arrowcontainer > .panel-arrowcontent {
overflow: hidden;
}
@ -1693,8 +1692,6 @@ menuitem[checked="true"].subviewbutton > .menu-iconic-left {
}
.panel-mainview[panelid=customizationui-widget-panel],
#customizationui-widget-multiview > .panel-viewcontainer,
#customizationui-widget-multiview > .panel-viewcontainer > .panel-viewstack,
#PanelUI-panicView > .panel-subview-body,
#PanelUI-panicView {
overflow: visible;
@ -2034,10 +2031,6 @@ photonpanelmultiview .PanelUI-subView toolbarseparator {
margin-inline-end: 0;
}
photonpanelmultiview#customizationui-widget-multiview > .panel-viewcontainer {
overflow: hidden;
}
/* This is explicitly overriding the overflow properties set above. */
photonpanelmultiview .cui-widget-panelview {
overflow-x: visible;

View File

@ -1,6 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M14.5 8c-.971 0-1 1-1.75 1a.765.765 0 0 1-.75-.75V5a1 1 0 0 0-1-1H7.75A.765.765 0 0 1 7 3.25c0-.75 1-.779 1-1.75C8 .635 7.1 0 6 0S4 .635 4 1.5c0 .971 1 1 1 1.75a.765.765 0 0 1-.75.75H1a1 1 0 0 0-1 1v2.25A.765.765 0 0 0 .75 8c.75 0 .779-1 1.75-1C3.365 7 4 7.9 4 9s-.635 2-1.5 2c-.971 0-1-1-1.75-1a.765.765 0 0 0-.75.75V15a1 1 0 0 0 1 1h3.25a.765.765 0 0 0 .75-.75c0-.75-1-.779-1-1.75 0-.865.9-1.5 2-1.5s2 .635 2 1.5c0 .971-1 1-1 1.75a.765.765 0 0 0 .75.75H11a1 1 0 0 0 1-1v-3.25a.765.765 0 0 1 .75-.75c.75 0 .779 1 1.75 1 .865 0 1.5-.9 1.5-2s-.635-2-1.5-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 893 B

View File

@ -0,0 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<path fill="context-fill" d="M13 1H3a3.007 3.007 0 0 0-3 3v8a3.009 3.009 0 0 0 3 3h10a3.005 3.005 0 0 0 3-3V4a3.012 3.012 0 0 0-3-3zM3 3h10a1 1 0 0 1 1 1v1H2V4a1 1 0 0 1 1-1zm11 3v1H2V6zm-1 7H3a1 1 0 0 1-1-1V8h12v4a1 1 0 0 1-1 1z"/>
</svg>

After

Width:  |  Height:  |  Size: 538 B

View File

@ -676,7 +676,7 @@ groupbox {
}
#searchInput {
width: 230px;
width: 250px;
margin: 20px 0;
}

View File

@ -102,7 +102,6 @@
skin/classic/browser/fxa/ios@2x.png (../shared/fxa/ios@2x.png)
skin/classic/browser/addons.svg (../shared/icons/addons.svg)
skin/classic/browser/arrow-dropdown-12.svg (../shared/icons/arrow-dropdown-12.svg)
skin/classic/browser/arrow-dropdown-16.svg (../shared/icons/arrow-dropdown-16.svg)
skin/classic/browser/arrow-left.svg (../shared/icons/arrow-left.svg)
@ -158,6 +157,7 @@
skin/classic/browser/stop-to-reload.svg (../shared/icons/stop-to-reload.svg)
skin/classic/browser/sync.svg (../shared/icons/sync.svg)
skin/classic/browser/synced-tabs.svg (../shared/icons/synced-tabs.svg)
skin/classic/browser/toolbar.svg (../shared/icons/toolbar.svg)
skin/classic/browser/webIDE.svg (../shared/icons/webIDE.svg)
skin/classic/browser/zoom-in.svg (../shared/icons/zoom-in.svg)
skin/classic/browser/zoom-out.svg (../shared/icons/zoom-out.svg)

View File

@ -23,7 +23,7 @@
}
#appMenu-addons-button {
list-style-image: url(chrome://browser/skin/addons.svg);
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.svg);
}
#appMenu-preferences-button {
@ -98,6 +98,14 @@
list-style-image: url("chrome://browser/skin/sidebars.svg");
}
#panelMenu_bookmarkingTools {
list-style-image: url("chrome://browser/skin/developer.svg");
}
#panelMenu_viewBookmarksToolbar {
list-style-image: url("chrome://browser/skin/toolbar.svg");
}
#appMenu-library-bookmarks-button,
#panelMenuBookmarkThisPage {
list-style-image: url("chrome://browser/skin/bookmark-hollow.svg");
@ -108,7 +116,8 @@
}
#bookmarks-menu-button[cui-areatype="menu-panel"],
toolbarpaletteitem[place="palette"] > #bookmarks-menu-button {
toolbarpaletteitem[place="palette"] > #bookmarks-menu-button,
#panelMenu_toggleBookmarksMenu {
list-style-image: url("chrome://browser/skin/bookmark-star-on-tray.svg");
}

View File

@ -99,7 +99,7 @@
%ifndef XP_MACOSX
/* Allow room for the checkbox drawn as a background image at the start of the toolbarbutton */
#sidebarMenu-popup .subviewbutton-iconic > .toolbarbutton-icon {
padding-inline-start: 16px;
margin-inline-start: 16px;
}
#sidebarMenu-popup .subviewbutton-iconic > .toolbarbutton-text {
padding-inline-start: 0;

View File

@ -2,6 +2,5 @@
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="context-fill">
<rect x="7" y="1" width="2" height="14"/>
<rect x="1" y="7" width="14" height="2"/>
<path d="M14 7H9V2a1 1 0 0 0-2 0v5H2a1 1 0 1 0 0 2h5v5a1 1 0 0 0 2 0V9h5a1 1 0 0 0 0-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 396 B

View File

@ -206,7 +206,7 @@ toolbar:not([brighttext]) #bookmarks-menu-button[starred] > .toolbarbutton-menub
}
#add-ons-button {
list-style-image: url("chrome://browser/skin/addons.svg");
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.svg");
}
#open-file-button {

View File

@ -1109,7 +1109,7 @@ html|*.addon-webext-perm-list {
}
.addon-addon-icon {
list-style-image: url("chrome://browser/skin/addons.svg");
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.svg");
}
.addon-toolbar-icon {

View File

@ -2405,12 +2405,45 @@ Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
return true;
}
nsresult
Element::SetSingleClassFromParser(nsIAtom* aSingleClassName)
{
// Keep this in sync with SetAttr and SetParsedAttr below.
if (!mAttrsAndChildren.CanFitMoreAttrs()) {
return NS_ERROR_FAILURE;
}
nsAttrValue value(aSingleClassName);
nsIDocument* document = GetComposedDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, false);
// In principle, BeforeSetAttr should be called here if a node type
// existed that wanted to do something special for class, but there
// is no such node type, so calling SetMayHaveClass() directly.
SetMayHaveClass();
return SetAttrAndNotify(kNameSpaceID_None,
nsGkAtoms::_class,
nullptr, // prefix
nullptr, // old value
value,
static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION),
false, // hasListeners
false, // notify
kCallAfterSetAttr,
document,
updateBatch);
}
nsresult
Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
bool aNotify)
{
// Keep this in sync with SetParsedAttr below
// Keep this in sync with SetParsedAttr below and SetSingleClassFromParser
// above.
NS_ENSURE_ARG_POINTER(aName);
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
@ -2475,7 +2508,7 @@ Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
nsIAtom* aPrefix, nsAttrValue& aParsedValue,
bool aNotify)
{
// Keep this in sync with SetAttr above
// Keep this in sync with SetAttr and SetSingleClassFromParser above
NS_ENSURE_ARG_POINTER(aName);
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
@ -2709,6 +2742,10 @@ Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
// If it is ever made to be exact, we probably need to handle this
// similarly to how ids are handled in PreIdMaybeChange and
// PostIdMaybeChange.
// Note that SetSingleClassFromParser inlines BeforeSetAttr and
// calls SetMayHaveClass directly. Making a subclass take action
// on the class attribute in a BeforeSetAttr override would
// require revising SetSingleClassFromParser.
SetMayHaveClass();
}
}

View File

@ -706,6 +706,13 @@ public:
uint8_t* aModType, bool* aHasListeners,
bool* aOldValueSet);
/**
* Sets the class attribute to a value that contains no whitespace.
* Assumes that we are not notifying and that the attribute hasn't been
* set previously.
*/
nsresult SetSingleClassFromParser(nsIAtom* aSingleClassName);
virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, bool aNotify) override;
// aParsedValue receives the old value of the attribute. That's useful if

View File

@ -0,0 +1,29 @@
<html>
<head>
<script>
try { o1 = document.createElement("tr") } catch(e) { }
try { o2 = document.createElement("td") } catch(e) { }
try { o3 = document.createElement("tr") } catch(e) { }
try { o4 = document.createElement("div") } catch(e) { }
try { o5 = document.createElement("input") } catch(e) { }
try { o6 = document.createElement('map') } catch(e) { }
try { o7 = document.createElement('select') } catch(e) { }
try { o8 = document.createElement("canvas") } catch(e) { }
try { o9 = document.createElement("area") } catch(e) { };
try { o1.appendChild(o2) } catch(e) { }
try { document.documentElement.appendChild(o3) } catch(e) { }
try { document.documentElement.appendChild(o4) } catch(e) { }
try { document.documentElement.appendChild(o6) } catch(e) { }
try { o3.appendChild(o7) } catch(e) { }
try { o4.appendChild(o8) } catch(e) { }
try { o3.appendChild(o5); } catch(e) { }
try { o3.appendChild(o1); } catch(e) { }
try { o6.contentEditable = "true" } catch(e) { };
try { o6.offsetHeight } catch(e) { };
try { o4.appendChild(o9) } catch(e) { };
try { o2.insertAdjacentHTML("beforeBegin", "<button id='id0'></button>\n"); } catch(e) { }
try { document.replaceChild(document.documentElement, document.documentElement); } catch(e) { }
try { document.execCommand("selectall",false,null) } catch(e) { }
</script>
</head>
</html>

View File

@ -221,3 +221,4 @@ load xhr_empty_datauri.html
load xhr_html_nullresponse.html
load 1383478.html
load 1383780.html
pref(clipboard.autocopy,true) load 1385272-1.html

View File

@ -1018,6 +1018,14 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
return EncodeToStringWithMaxLength(0, aOutputString);
}
static bool ParentIsTR(nsIContent* aContent) {
mozilla::dom::Element* parent = aContent->GetParentElement();
if (!parent) {
return false;
}
return parent->IsHTMLElement(nsGkAtoms::tr);
}
NS_IMETHODIMP
nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
nsAString& aOutputString)
@ -1088,7 +1096,7 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
if (content && content->IsHTMLElement(nsGkAtoms::tr)) {
if (content && content->IsHTMLElement(nsGkAtoms::tr) && !ParentIsTR(content)) {
nsINode* n = content;
if (!prevNode) {
// Went from a non-<tr> to a <tr>

View File

@ -2462,17 +2462,15 @@ DecodingState::MaybeStartBuffering()
return;
}
bool shouldBuffer;
if (Reader()->UseBufferingHeuristics()) {
shouldBuffer = IsExpectingMoreData()
&& mMaster->HasLowDecodedData()
&& mMaster->HasLowBufferedData();
} else {
shouldBuffer =
(mMaster->OutOfDecodedAudio() && mMaster->IsWaitingAudioData())
|| (mMaster->OutOfDecodedVideo() && mMaster->IsWaitingVideoData());
// Note we could have a wait promise pending when playing non-MSE EME.
if ((mMaster->OutOfDecodedAudio() && mMaster->IsWaitingAudioData()) ||
(mMaster->OutOfDecodedVideo() && mMaster->IsWaitingVideoData())) {
SetState<BufferingState>();
return;
}
if (shouldBuffer) {
if (Reader()->UseBufferingHeuristics() && mMaster->HasLowDecodedData() &&
mMaster->HasLowBufferedData() && !mMaster->mCanPlayThrough) {
SetState<BufferingState>();
}
}
@ -2547,17 +2545,24 @@ BufferingState::Step()
TimeStamp now = TimeStamp::Now();
MOZ_ASSERT(!mBufferingStart.IsNull(), "Must know buffering start time.");
// With buffering heuristics we will remain in the buffering state if
// we've not decoded enough data to begin playback, or if we've not
// downloaded a reasonable amount of data inside our buffering time.
if (Reader()->UseBufferingHeuristics()) {
if (mMaster->IsWaitingAudioData() || mMaster->IsWaitingVideoData()) {
// Can't exit buffering when we are still waiting for data.
// Note we don't schedule next loop for we will do that when the wait
// promise is resolved.
return;
}
// With buffering heuristics, we exit buffering state when we:
// 1. can play through or
// 2. time out (specified by mBufferingWait) or
// 3. have enough buffered data.
TimeDuration elapsed = now - mBufferingStart;
bool isLiveStream = Resource()->IsLiveStream();
if ((isLiveStream || !mMaster->mCanPlayThrough)
&& elapsed
< TimeDuration::FromSeconds(mBufferingWait * mMaster->mPlaybackRate)
&& mMaster->HasLowBufferedData(TimeUnit::FromSeconds(mBufferingWait))
&& IsExpectingMoreData()) {
TimeDuration timeout =
TimeDuration::FromSeconds(mBufferingWait * mMaster->mPlaybackRate);
bool stopBuffering =
mMaster->mCanPlayThrough || elapsed >= timeout ||
!mMaster->HasLowBufferedData(TimeUnit::FromSeconds(mBufferingWait));
if (!stopBuffering) {
SLOG("Buffering: wait %ds, timeout in %.3lfs",
mBufferingWait, mBufferingWait - elapsed.ToSeconds());
mMaster->ScheduleStateMachineIn(TimeUnit::FromMicroseconds(USECS_PER_S));

View File

@ -526,18 +526,78 @@ InterpolateForGecko(const ValueWrapper* aStartWrapper,
return NS_ERROR_FAILURE;
}
static bool
IsPropertyDiscretelyAnimatable(nsCSSPropertyID aProperty)
{
// For shorthands, Servo_Property_IsDiscreteAnimatable will always return
// false. That makes sense for shorthands like 'font' which have smoothly
// interpolable longhand components. However, for shorthands where all the
// components are discretely animatable, like 'font-variant', we should
// treat the shorthand as discretely animatable so that we apply SMIL's
// special discrete handling to it and all its longhand components.
if (nsCSSProps::IsShorthand(aProperty)) {
// We could iterate over all the longhand components and call
// Servo_Property_IsDiscreteAnimatable on each of them, but that's a lot of
// FFI calls do be doing each time we interpolate. Instead, since there are
// only about six shorthands in the set of properties that can be animated
// by SMIL, we just hard code the discrete ones below then add a debug-mode
// check that this list matches what the result would be if we performed
// all the FFI calls.
bool result;
switch (aProperty) {
case eCSSProperty_font_variant:
case eCSSProperty_marker:
case eCSSProperty_overflow:
result = true;
break;
default:
result = false;
break;
}
#ifdef DEBUG
bool resultAccordingToServo = true;
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty,
CSSEnabledState::eForAllContent) {
// If the shorthand has one or more non-discrete components, it should not
// be treated as discrete.
if (!Servo_Property_IsDiscreteAnimatable(*p)) {
resultAccordingToServo = false;
}
}
MOZ_ASSERT(result == resultAccordingToServo,
"Gecko and Servo should agree on which shorthands should be"
" treated as discretely animatable");
#endif
return result;
}
return Servo_Property_IsDiscreteAnimatable(aProperty);
}
static nsresult
InterpolateForServo(const ValueWrapper* aStartWrapper,
const ValueWrapper& aEndWrapper,
double aUnitDistance,
nsSMILValue& aResult)
{
// For discretely-animated properties Servo_AnimationValues_Interpolate will
// perform the discrete animation (i.e. 50% flip) and return a success result.
// However, SMIL has its own special discrete animation behavior that it uses
// when keyTimes are specified, but we won't run that unless that this method
// returns a failure to indicate that the property cannot be smoothly
// interpolated, i.e. that we need to use a discrete calcMode.
if (IsPropertyDiscretelyAnimatable(aEndWrapper.mPropID)) {
return NS_ERROR_FAILURE;
}
ServoAnimationValues results;
size_t len = aEndWrapper.mServoValues.Length();
results.SetCapacity(len);
MOZ_ASSERT(!aStartWrapper || aStartWrapper->mServoValues.Length() == len,
"Start and end values length should be the same if "
"The start value exists");
"the start value exists");
for (size_t i = 0; i < len; i++) {
const RefPtr<RawServoAnimationValue>*
startValue = aStartWrapper

View File

@ -42,7 +42,6 @@ skip-if = toolkit == 'android'
[test_smilInvalidValues.html]
[test_smilKeySplines.xhtml]
[test_smilKeyTimes.xhtml]
skip-if = stylo
[test_smilKeyTimesPacedMode.xhtml]
[test_smilMappedAttrFromBy.xhtml]
skip-if = stylo

View File

@ -19,12 +19,8 @@ interface StackFrame;
Exposed=(Window,Worker)]
interface ExceptionMembers
{
// A custom message set by the thrower.
readonly attribute DOMString message;
// The nsresult associated with this exception.
readonly attribute unsigned long result;
// The name of the error code (ie, a string repr of |result|).
readonly attribute DOMString name;
// Filename location. This is the location that caused the
// error, which may or may not be a source file location.
@ -57,6 +53,10 @@ interface ExceptionMembers
[NoInterfaceObject, Exposed=(Window,Worker)]
interface Exception {
// The name of the error code (ie, a string repr of |result|).
readonly attribute DOMString name;
// A custom message set by the thrower.
readonly attribute DOMString message;
// A generic formatter - make it suitable to print, etc.
stringifier;
};
@ -69,6 +69,12 @@ Exception implements ExceptionMembers;
Exposed=(Window, Worker),
Constructor(optional DOMString message = "", optional DOMString name)]
interface DOMException {
// The name of the error code (ie, a string repr of |result|).
readonly attribute DOMString name;
// A custom message set by the thrower.
readonly attribute DOMString message;
readonly attribute unsigned short code;
const unsigned short INDEX_SIZE_ERR = 1;
const unsigned short DOMSTRING_SIZE_ERR = 2; // historical
const unsigned short HIERARCHY_REQUEST_ERR = 3;
@ -94,8 +100,6 @@ interface DOMException {
const unsigned short TIMEOUT_ERR = 23;
const unsigned short INVALID_NODE_TYPE_ERR = 24;
const unsigned short DATA_CLONE_ERR = 25;
readonly attribute unsigned short code;
};
// XXXkhuey copy all of Gecko's non-standard stuff onto DOMException, but leave

View File

@ -74,6 +74,9 @@ ComputeImageFlags(ImageURL* uri, const nsCString& aMimeType, bool isMultiPart)
if (isMultiPart) {
imageFlags |= Image::INIT_FLAG_TRANSIENT;
}
imageFlags |= Image::INIT_FLAG_SYNC_LOAD;
// Always synchronously decode metadata (including size) so as to avoid
// unnecessary reflows.
return imageFlags;
}

View File

@ -125,6 +125,7 @@ skip-if = true # disabled - See bug 579139
skip-if = os == 'android'
[test_bug1180105.html]
[test_bug1217571.html]
[test_bug1325080.html]
[test_bullet_animation.html]
skip-if = os == 'android'
[test_changeOfSource.html]

View File

@ -0,0 +1,37 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1325080
-->
<head>
<title>Test for Bug 1325080</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1325080">Mozilla Bug 1325080</a>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 1325080 **/
SimpleTest.waitForExplicitFinish();
function createImage() {
// This function's code comes from the Acid3 test #72
document.open();
document.write('<!DOCTYPE html><head><style>img { height: 10px; }</style></head><body><img src="data:image/gif;base64,R0lGODlhAQABAID%2FAMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D" alt="alt-text"></body>');
document.close();
}
window.onload = function() {
createImage();
SimpleTest.executeSoon(() => {
ok(document.images[0].height == 10, "Style should set height of image.");
SimpleTest.finish();
});
}
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<style>
@keyframes anim {
from { content: 'content'; }
to { content: ''; }
}
#target::before {
content: 'initial';
animation: anim 100s paused;
}
</style>
<div id='target'></div>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<style>
@keyframes anim {
from { content: ''; }
to { content: 'content'; }
}
#target::before {
content: 'initial';
animation: anim 100s linear -50s paused;
}
</style>
<div id='target'></div>
</html>

View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<style>
#target::before {
content: 'content';
}
</style>
<div id='target'></div>
</html>

View File

@ -54,4 +54,6 @@ fails == background-position-important.html background-position-ref.html # This
== stop-animation-on-discarded-pseudo-element.html about:blank
== updating-animation-on-pseudo-element.html updating-animation-on-pseudo-element-ref.html
== content-on-pseudo-element-at-beginning.html content-on-pseudo-element-ref.html
== content-on-pseudo-element-at-half.html content-on-pseudo-element-ref.html
== reframe-and-animation-starts-at-the-same-time.html reframe-and-animation-starts-at-the-same-time-ref.html

View File

@ -72,16 +72,10 @@ var skippedProperties = {
"mask-position-y": true, // Bug 1387946
"mask-size": true, // Bug 1387946
"box-shadow": true, // Bug 1387973
"caret-color": true, // Bug 1387951
"clip": true, // Bug 1387951
"column-count": true, // Bug 1387939
"-moz-image-region": true, // Bug 1387951
"order": true, // Bug 1387939
"stroke-dasharray": true, // Bug 1387986
"stroke-dashoffset": true, // Bug 1369614
"stroke-width": true, // Bug 1369614
"text-shadow": true, // Bug 1387973
"z-index": true, // Bug 1387939
};
var supported_properties = {

View File

@ -30,8 +30,13 @@ const BUF_SIZE_LIMIT: usize = 1024 * 1024;
// Max table length. Calculating in worth case for one week long video, one
// frame per table entry in 30 fps.
#[cfg(target_pointer_width = "64")]
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24 * 7;
// Reduce max table length if it is in 32 arch for memory problem.
#[cfg(target_pointer_width = "32")]
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24;
static DEBUG_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
pub fn set_debug_mode(mode: bool) {
@ -1333,13 +1338,12 @@ fn find_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
let tag = des.read_u8()?;
let mut end = 0;
// Extension descriptor could be variable size from 0x80 to
// 0x80 0x80 0x80, the descriptor length is the byte after that,
// so it loops four times.
// MSB of extend_or_len indicates more bytes, up to 4 bytes.
for _ in 0..4 {
let extend_or_len = des.read_u8()?;
if extend_or_len < 0x80 {
end = extend_or_len + des.position() as u8;
end = (end << 7) + (extend_or_len & 0x7F);
if (extend_or_len & 0x80) == 0 {
end += des.position() as u8;
break;
}
};

View File

@ -974,6 +974,23 @@ fn read_esds_one_byte_extension_descriptor() {
assert_eq!(es.audio_channel_count, Some(2));
}
#[test]
fn read_esds_byte_extension_descriptor() {
let mut stream = make_box(BoxSize::Auto, b"esds", |s| {
s.B32(0) // reserved
.B16(0x0003)
.B16(0x8181) // extension byte length 0x81
.append_repeated(0, 0x81)
});
let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap();
match super::read_esds(&mut stream) {
Ok(_) => (),
_ => panic!("fail to parse descriptor extension byte length"),
}
}
#[test]
fn read_f4v_stsd() {
let mut stream = make_box(BoxSize::Auto, b".mp3", |s| {

View File

@ -2,7 +2,7 @@
# Script to update mp4parse-rust sources to latest upstream
# Default version.
VER=7563263b6804a81986cc93b557fe05bd57fd57b3
VER=1d2d69df3380139ee208f58181c73b1947c91ac2
# Accept version or commit from the command line.
if test -n "$1"; then

View File

@ -138,8 +138,9 @@ template<typename Ret, typename FunType, typename... Args>
class runnable_args_func_ret : public detail::runnable_args_base<detail::ReturnsResult>
{
public:
runnable_args_func_ret(Ret* ret, FunType f, Args&&... args)
: mReturn(ret), mFunc(f), mArgs(Forward<Args>(args)...)
template<typename... Arguments>
runnable_args_func_ret(Ret* ret, FunType f, Arguments&&... args)
: mReturn(ret), mFunc(f), mArgs(Forward<Arguments>(args)...)
{}
NS_IMETHOD Run() {
@ -154,18 +155,19 @@ private:
};
template<typename R, typename FunType, typename... Args>
runnable_args_func_ret<R, FunType, Args...>*
WrapRunnableNMRet(R* ret, FunType f, Args... args)
runnable_args_func_ret<R, FunType, typename mozilla::Decay<Args>::Type...>*
WrapRunnableNMRet(R* ret, FunType f, Args&&... args)
{
return new runnable_args_func_ret<R, FunType, Args...>(ret, f, Move(args)...);
return new runnable_args_func_ret<R, FunType, typename mozilla::Decay<Args>::Type...>(ret, f, Forward<Args>(args)...);
}
template<typename Class, typename M, typename... Args>
class runnable_args_memfn : public detail::runnable_args_base<detail::NoResult>
{
public:
runnable_args_memfn(Class obj, M method, Args&&... args)
: mObj(obj), mMethod(method), mArgs(Forward<Args>(args)...)
template<typename... Arguments>
runnable_args_memfn(Class obj, M method, Arguments&&... args)
: mObj(obj), mMethod(method), mArgs(Forward<Arguments>(args)...)
{}
NS_IMETHOD Run() {
@ -180,18 +182,19 @@ private:
};
template<typename Class, typename M, typename... Args>
runnable_args_memfn<Class, M, Args...>*
WrapRunnable(Class obj, M method, Args... args)
runnable_args_memfn<Class, M, typename mozilla::Decay<Args>::Type...>*
WrapRunnable(Class obj, M method, Args&&... args)
{
return new runnable_args_memfn<Class, M, Args...>(obj, method, Move(args)...);
return new runnable_args_memfn<Class, M, typename mozilla::Decay<Args>::Type...>(obj, method, Forward<Args>(args)...);
}
template<typename Ret, typename Class, typename M, typename... Args>
class runnable_args_memfn_ret : public detail::runnable_args_base<detail::ReturnsResult>
{
public:
runnable_args_memfn_ret(Ret* ret, Class obj, M method, Args... args)
: mReturn(ret), mObj(obj), mMethod(method), mArgs(Forward<Args>(args)...)
template<typename... Arguments>
runnable_args_memfn_ret(Ret* ret, Class obj, M method, Arguments... args)
: mReturn(ret), mObj(obj), mMethod(method), mArgs(Forward<Arguments>(args)...)
{}
NS_IMETHOD Run() {
@ -207,10 +210,10 @@ private:
};
template<typename R, typename Class, typename M, typename... Args>
runnable_args_memfn_ret<R, Class, M, Args...>*
WrapRunnableRet(R* ret, Class obj, M method, Args... args)
runnable_args_memfn_ret<R, Class, M, typename mozilla::Decay<Args>::Type...>*
WrapRunnableRet(R* ret, Class obj, M method, Args&&... args)
{
return new runnable_args_memfn_ret<R, Class, M, Args...>(ret, obj, method, Move(args)...);
return new runnable_args_memfn_ret<R, Class, M, typename mozilla::Decay<Args>::Type...>(ret, obj, method, Forward<Args>(args)...);
}
static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, detail::runnable_args_base<detail::NoResult> *runnable, uint32_t flags) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

After

Width:  |  Height:  |  Size: 120 B

View File

@ -5,7 +5,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/button_pressed_action_orange_round" />
android:drawable="@drawable/button_pressed_action_photon_round" />
<item android:state_enabled="true"
android:drawable="@drawable/button_enabled_action_orange_round" />
android:drawable="@drawable/button_enabled_action_photon_round" />
</selector>

View File

@ -5,7 +5,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@color/action_orange" />
<solid android:color="@color/ob_click" />
<corners
android:radius="@dimen/standard_corner_radius" />
</shape>

View File

@ -5,7 +5,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@color/action_orange_pressed" />
<solid android:color="@color/ob_press" />
<corners
android:radius="@dimen/standard_corner_radius" />
android:radius="5dp" />
</shape>

View File

@ -20,8 +20,8 @@
<ImageView android:id="@+id/firstrun_image"
android:layout_width="wrap_content"
android:layout_height="@dimen/firstrun_background_height"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="18dp"
android:scaleType="fitCenter"
android:layout_gravity="center"
android:adjustViewBounds="true"/>
@ -53,6 +53,7 @@
android:padding="30dp"
android:gravity="center"
android:textAppearance="@style/TextAppearance.FirstrunRegular.Link"
android:textAllCaps="true"
android:text="@string/firstrun_button_next"/>
</LinearLayout>
</ScrollView>

View File

@ -21,8 +21,8 @@
<ImageView android:id="@+id/firstrun_image"
android:layout_width="wrap_content"
android:layout_height="@dimen/firstrun_background_height"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="18dp"
android:scaleType="fitCenter"
android:layout_gravity="center"
android:adjustViewBounds="true"/>
@ -31,24 +31,37 @@
android:layout_width="@dimen/firstrun_content_width"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="40dp"
android:textAppearance="@style/TextAppearance.FirstrunLight.Main"/>
<TextView android:id="@+id/firstrun_subtext"
android:layout_width="@dimen/firstrun_content_width"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:paddingBottom="30dp"
android:gravity="center"
android:textAppearance="@style/TextAppearance.FirstrunRegular.Body"/>
<Button android:id="@+id/welcome_account"
style="@style/Widget.Firstrun.Button"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:layout_gravity="center"
android:text="@string/firstrun_signin_button"/>
<View android:layout_weight="1"
android:layout_height="0dp"
android:layout_width="match_parent"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/welcome_browse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp"
android:text="@string/firstrun_welcome_button_browser"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.FirstrunRegular.Link"/>
</RelativeLayout>
<TextView android:id="@+id/welcome_browse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="30dp"
android:gravity="center"
android:textAppearance="@style/TextAppearance.FirstrunRegular.Link"/>
</LinearLayout>
</ScrollView>

View File

@ -56,6 +56,7 @@
android:layout_gravity="center"
android:layout_marginBottom="20dp"
android:background="@drawable/button_background_action_blue_round"
android:textAllCaps="true"
android:text="@string/firstrun_welcome_button_browser" />
<TextView

View File

@ -116,7 +116,7 @@
android:layout_width="@dimen/overlay_prompt_button_width"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:text="@string/tab_queue_prompt_positive_action_button"
android:textColor="@android:color/white"
android:textSize="16sp"
@ -128,7 +128,7 @@
android:layout_width="@dimen/overlay_prompt_button_width"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:text="@string/tab_queue_prompt_settings_button"
android:textColor="@android:color/white"
android:textSize="16sp"

View File

@ -92,7 +92,7 @@
android:layout_height="52dp"
android:layout_gravity="center"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:text="@string/tracking_protection_prompt_action_button"
android:textColor="@android:color/white"
android:textSize="16sp"

View File

@ -137,11 +137,16 @@
<color name="affirmative_green">#6FBE4A</color>
<color name="rejection_red">#D23228</color>
<color name="action_orange">#E66000</color>
<color name="action_orange_pressed">#DC5600</color>
<color name="link_blue">#0096DD</color>
<color name="link_blue_pressed">#0082C6</color>
<color name="private_browsing_purple">#CF68FF</color>
<!-- On boarding -->
<color name="ob_click">#0A84FF</color>
<color name="ob_press">#003EAA</color>
<color name="ob_title">#212121</color>
<color name="ob_subtitle">#737373</color>
<color name="placeholder_active_grey">#222222</color>
<color name="placeholder_grey">#777777</color>
<color name="private_toolbar_grey">#292C29</color>

View File

@ -727,18 +727,18 @@
<style name="TextAppearance.FirstrunLight.Main">
<item name="android:textSize">20sp</item>
<item name="android:textColor">@color/text_and_tabs_tray_grey</item>
<item name="android:textColor">@color/ob_title</item>
</style>
<style name="TextAppearance.FirstrunRegular.Body">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/placeholder_grey</item>
<item name="android:textColor">@color/ob_subtitle</item>
<item name="android:lineSpacingMultiplier">1.25</item>
</style>
<style name="TextAppearance.FirstrunRegular.Link">
<item name="android:textSize">16sp</item>
<item name="android:textColor">@color/link_blue</item>
<item name="android:textColor">@color/ob_click</item>
</style>
<!-- Remote Tabs home panel -->

View File

@ -1013,6 +1013,7 @@ public class BrowserApp extends GeckoApp
if (prefs.getBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED_OLD, true) &&
prefs.getBoolean(FirstrunAnimationContainer.PREF_FIRSTRUN_ENABLED, true)) {
showSplashScreen = false;
if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
// Check to see if a distribution has turned off the first run pager.
final Distribution distribution = Distribution.getInstance(BrowserApp.this);
@ -2833,12 +2834,6 @@ public class BrowserApp extends GeckoApp
}
private void showFirstrunPager() {
if (Experiments.isInExperimentLocal(this, Experiments.ONBOARDING3_A)) {
Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING3_A);
GeckoSharedPrefs.forProfile(this).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING3_A).apply();
Telemetry.stopUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING3_A);
return;
}
if (mFirstrunAnimationContainer == null) {
final ViewStub firstrunPagerStub = (ViewStub) findViewById(R.id.firstrun_pager_stub);

View File

@ -68,23 +68,6 @@ public class Experiments {
// Enable processing of background telemetry.
public static final String ENABLE_PROCESSING_BACKGROUND_TELEMETRY = "process-background-telemetry";
/**
* Returns if a user is in certain local experiment.
* @param experiment Name of experiment to look up
* @return returns value for experiment or false if experiment does not exist.
*/
public static boolean isInExperimentLocal(Context context, String experiment) {
if (SwitchBoard.isInBucket(context, 0, 20)) {
return Experiments.ONBOARDING3_A.equals(experiment);
} else if (SwitchBoard.isInBucket(context, 20, 60)) {
return Experiments.ONBOARDING3_B.equals(experiment);
} else if (SwitchBoard.isInBucket(context, 60, 100)) {
return Experiments.ONBOARDING3_C.equals(experiment);
} else {
return false;
}
}
/**
* Returns list of all active experiments, remote and local.
* @return List of experiment names Strings

View File

@ -29,7 +29,7 @@ public class DataPanel extends FirstrunPanel {
public void onClick(View view) {
// Set new state.
isEnabled = !isEnabled;
int newResource = isEnabled ? R.drawable.firstrun_data_on : R.drawable.firstrun_data_off;
int newResource = isEnabled ? R.drawable.firstrun_data : R.drawable.firstrun_data;
((ImageView) view).setImageResource(newResource);
if (isEnabled) {
// Always block images.

View File

@ -27,7 +27,8 @@ import org.mozilla.gecko.preferences.GeckoPreferences;
public class FirstrunAnimationContainer extends LinearLayout {
// See bug 1330714. Need NON_PREF_PREFIX to set from distribution.
public static final String PREF_FIRSTRUN_ENABLED_OLD = "startpane_enabled";
public static final String PREF_FIRSTRUN_ENABLED = GeckoPreferences.NON_PREF_PREFIX + "startpane_enabled";
// After 57, the pref name will be changed. Thus all user since 57 will check this new pref.
public static final String PREF_FIRSTRUN_ENABLED = GeckoPreferences.NON_PREF_PREFIX + "startpane_enabled_after_57";
public static interface OnFinishListener {
public void onFinish();

View File

@ -20,6 +20,7 @@ import com.booking.rtlviewpager.RtlViewPager;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
import org.mozilla.gecko.fxa.FirefoxAccounts;
import org.mozilla.gecko.home.HomePager.Decor;
import org.mozilla.gecko.home.TabMenuStrip;
import org.mozilla.gecko.restrictions.Restrictions;
@ -67,6 +68,8 @@ public class FirstrunPager extends RtlViewPager {
if (Restrictions.isRestrictedProfile(context)) {
panels = FirstrunPagerConfig.getRestricted();
} else if (FirefoxAccounts.firefoxAccountsExist(context)) {
panels = FirstrunPagerConfig.forFxAUser(appContext);
} else {
panels = FirstrunPagerConfig.getDefault(appContext);
}

View File

@ -26,25 +26,20 @@ public class FirstrunPagerConfig {
public static List<FirstrunPanelConfig> getDefault(Context context) {
final List<FirstrunPanelConfig> panels = new LinkedList<>();
panels.add(SimplePanelConfigs.welcomePanelConfig);
panels.add(SimplePanelConfigs.privatePanelConfig);
panels.add(SimplePanelConfigs.customizePanelConfig);
panels.add(SimplePanelConfigs.syncPanelConfig);
return panels;
}
public static List<FirstrunPanelConfig> forFxAUser(Context context) {
final List<FirstrunPanelConfig> panels = new LinkedList<>();
panels.add(SimplePanelConfigs.welcomePanelConfig);
panels.add(SimplePanelConfigs.privatePanelConfig);
panels.add(SimplePanelConfigs.customizeLastPanelConfig);
if (Experiments.isInExperimentLocal(context, Experiments.ONBOARDING3_B)) {
panels.add(SimplePanelConfigs.urlbarPanelConfig);
panels.add(SimplePanelConfigs.bookmarksPanelConfig);
panels.add(SimplePanelConfigs.dataPanelConfig);
panels.add(SimplePanelConfigs.syncPanelConfig);
panels.add(SimplePanelConfigs.signInPanelConfig);
Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING3_B);
GeckoSharedPrefs.forProfile(context).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING3_B).apply();
} else if (Experiments.isInExperimentLocal(context, Experiments.ONBOARDING3_C)) {
panels.add(SimplePanelConfigs.tabqueuePanelConfig);
panels.add(SimplePanelConfigs.readerviewPanelConfig);
panels.add(SimplePanelConfigs.accountPanelConfig);
Telemetry.startUISession(TelemetryContract.Session.EXPERIMENT, Experiments.ONBOARDING3_C);
GeckoSharedPrefs.forProfile(context).edit().putString(Experiments.PREF_ONBOARDING_VERSION, Experiments.ONBOARDING3_C).apply();
} else {
Log.e(LOGTAG, "Not in an experiment!");
panels.add(SimplePanelConfigs.signInPanelConfig);
}
return panels;
}
@ -94,14 +89,12 @@ public class FirstrunPagerConfig {
}
private static class SimplePanelConfigs {
public static final FirstrunPanelConfig urlbarPanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_panel_title_welcome, R.drawable.firstrun_urlbar, R.string.firstrun_urlbar_message, R.string.firstrun_urlbar_subtext);
public static final FirstrunPanelConfig bookmarksPanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_bookmarks_title, R.drawable.firstrun_bookmarks, R.string.firstrun_bookmarks_message, R.string.firstrun_bookmarks_subtext);
public static final FirstrunPanelConfig dataPanelConfig = new FirstrunPanelConfig(DataPanel.class.getName(), R.string.firstrun_data_title, R.drawable.firstrun_data_off, R.string.firstrun_data_message, R.string.firstrun_data_subtext);
public static final FirstrunPanelConfig syncPanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_sync_title, R.drawable.firstrun_sync, R.string.firstrun_sync_message, R.string.firstrun_sync_subtext);
public static final FirstrunPanelConfig signInPanelConfig = new FirstrunPanelConfig(SyncPanel.class.getName(), R.string.pref_sync, R.drawable.firstrun_signin, R.string.firstrun_signin_message, R.string.firstrun_welcome_button_browser);
public static final FirstrunPanelConfig welcomePanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_panel_title_welcome, R.drawable.firstrun_welcome, R.string.firstrun_urlbar_message, R.string.firstrun_urlbar_subtext);
public static final FirstrunPanelConfig privatePanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_panel_title_privacy, R.drawable.firstrun_private, R.string.firstrun_privacy_message, R.string.firstrun_privacy_subtext);
public static final FirstrunPanelConfig customizePanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_panel_title_customize, R.drawable.firstrun_data, R.string.firstrun_customize_message, R.string.firstrun_customize_subtext);
public static final FirstrunPanelConfig customizeLastPanelConfig = new FirstrunPanelConfig(LastPanel.class.getName(), R.string.firstrun_panel_title_customize, R.drawable.firstrun_data, R.string.firstrun_customize_message, R.string.firstrun_customize_subtext);
public static final FirstrunPanelConfig syncPanelConfig = new FirstrunPanelConfig(SyncPanel.class.getName(), R.string.firstrun_sync_title, R.drawable.firstrun_sync, R.string.firstrun_sync_message, R.string.firstrun_sync_subtext);
public static final FirstrunPanelConfig tabqueuePanelConfig = new FirstrunPanelConfig(TabQueuePanel.class.getName(), R.string.firstrun_tabqueue_title, R.drawable.firstrun_tabqueue_off, R.string.firstrun_tabqueue_message_off, R.string.firstrun_tabqueue_subtext_off);
public static final FirstrunPanelConfig readerviewPanelConfig = new FirstrunPanelConfig(FirstrunPanel.class.getName(), R.string.firstrun_readerview_title, R.drawable.firstrun_readerview, R.string.firstrun_readerview_message, R.string.firstrun_readerview_subtext);
public static final FirstrunPanelConfig accountPanelConfig = new FirstrunPanelConfig(SyncPanel.class.getName(), R.string.firstrun_account_title, R.drawable.firstrun_account, R.string.firstrun_account_message, R.string.firstrun_button_notnow);
}
}

View File

@ -30,7 +30,7 @@ public class FirstrunPanel extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.firstrun_basepanel_checkable_fragment, container, false);
Bundle args = getArguments();
final Bundle args = getArguments();
if (args != null) {
final int imageRes = args.getInt(FirstrunPagerConfig.KEY_IMAGE);
final int textRes = args.getInt(FirstrunPagerConfig.KEY_TEXT);

View File

@ -0,0 +1,47 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* 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/. */
package org.mozilla.gecko.firstrun;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.mozilla.gecko.R;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract;
public class LastPanel extends FirstrunPanel {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
final ViewGroup root = (ViewGroup) inflater.inflate(R.layout.firstrun_basepanel_checkable_fragment, container, false);
final Bundle args = getArguments();
if (args != null) {
final int imageRes = args.getInt(FirstrunPagerConfig.KEY_IMAGE);
final int textRes = args.getInt(FirstrunPagerConfig.KEY_TEXT);
final int subtextRes = args.getInt(FirstrunPagerConfig.KEY_SUBTEXT);
((ImageView) root.findViewById(R.id.firstrun_image)).setImageResource(imageRes);
((TextView) root.findViewById(R.id.firstrun_text)).setText(textRes);
((TextView) root.findViewById(R.id.firstrun_subtext)).setText(subtextRes);
((TextView) root.findViewById(R.id.firstrun_link)).setText(R.string.firstrun_welcome_button_browser);
}
root.findViewById(R.id.firstrun_link).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-next");
close();
}
});
return root;
}
}

View File

@ -30,7 +30,7 @@ public class SyncPanel extends FirstrunPanel {
((ImageView) root.findViewById(R.id.firstrun_image)).setImageResource(imageRes);
((TextView) root.findViewById(R.id.firstrun_text)).setText(textRes);
((TextView) root.findViewById(R.id.welcome_browse)).setText(subtextRes);
((TextView) root.findViewById(R.id.firstrun_subtext)).setText(subtextRes);
}
root.findViewById(R.id.welcome_account).setOnClickListener(new View.OnClickListener() {

View File

@ -3,9 +3,14 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!ENTITY firstrun_panel_title_welcome "Welcome">
<!ENTITY firstrun_urlbar_message "Welcome to &brandShortName;">
<!ENTITY firstrun_urlbar_subtext "Find things faster with helpful search suggestion shortcuts.">
<!ENTITY firstrun_urlbar_message2 "Thanks for choosing &brandShortName;">
<!ENTITY firstrun_urlbar_subtext2 "A modern mobile browser from Mozilla, the non-profit committed to a free and open web.">
<!ENTITY firstrun_panel_title_privacy "Privacy">
<!ENTITY firstrun_privacy_message "Browse like no one\'s watching">
<!ENTITY firstrun_privacy_subtext "Private Browsing with Tracking Protection blocks trackers while you browse and wont remember your history when you finish browsing.">
<!ENTITY firstrun_panel_title_customize "Customize">
<!ENTITY firstrun_customize_message "Make Firefox your own.">
<!ENTITY firstrun_customize_subtext "Customize Firefox with add-ons. Block ads, add features, or choose a new theme to reflect your personality.">
<!ENTITY firstrun_bookmarks_title "History">
<!ENTITY firstrun_bookmarks_message "Your faves, front and center">
<!ENTITY firstrun_bookmarks_subtext "Get results from your bookmarks and history when you search.">
@ -13,8 +18,8 @@
<!ENTITY firstrun_data_message "Less data, more savings">
<!ENTITY firstrun_data_subtext2 "Turn off images to spend less data on every site you visit.">
<!ENTITY firstrun_sync_title "Sync">
<!ENTITY firstrun_sync_message "&brandShortName;, always by your side">
<!ENTITY firstrun_sync_subtext "Sync your tabs, passwords, and more everywhere you use it.">
<!ENTITY firstrun_sync_message2 "Pick up where you left off.">
<!ENTITY firstrun_sync_subtext2 "Use Sync to find the bookmarks, passwords, and other things you save to Firefox on all your devices.">
<!ENTITY firstrun_signin_message "Get connected, get started">
<!ENTITY firstrun_signin_button "Sign in to Sync">
<!ENTITY onboard_start_button_browser "Start Browsing">

View File

@ -648,6 +648,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'firstrun/FirstrunPager.java',
'firstrun/FirstrunPagerConfig.java',
'firstrun/FirstrunPanel.java',
'firstrun/LastPanel.java',
'firstrun/RestrictedWelcomePanel.java',
'firstrun/SyncPanel.java',
'firstrun/TabQueuePanel.java',

View File

@ -31,36 +31,26 @@
<string name="firstrun_panel_title_welcome">&firstrun_panel_title_welcome;</string>
<string name="firstrun_urlbar_message">&firstrun_urlbar_message;</string>
<string name="firstrun_urlbar_subtext">&firstrun_urlbar_subtext;</string>
<string name="firstrun_bookmarks_title">&firstrun_bookmarks_title;</string>
<string name="firstrun_bookmarks_message">&firstrun_bookmarks_message;</string>
<string name="firstrun_bookmarks_subtext">&firstrun_bookmarks_subtext;</string>
<string name="firstrun_data_title">&firstrun_data_title;</string>
<string name="firstrun_data_message">&firstrun_data_message;</string>
<string name="firstrun_data_subtext">&firstrun_data_subtext2;</string>
<string name="firstrun_urlbar_message">&firstrun_urlbar_message2;</string>
<string name="firstrun_urlbar_subtext">&firstrun_urlbar_subtext2;</string>
<string name="firstrun_panel_title_privacy">&firstrun_panel_title_privacy;</string>
<string name="firstrun_privacy_message">&firstrun_privacy_message;</string>
<string name="firstrun_privacy_subtext">&firstrun_privacy_subtext;</string>
<string name="firstrun_panel_title_customize">&firstrun_panel_title_customize;</string>
<string name="firstrun_customize_message">&firstrun_customize_message;</string>
<string name="firstrun_customize_subtext">&firstrun_customize_subtext;</string>
<string name="firstrun_sync_title">&firstrun_sync_title;</string>
<string name="firstrun_sync_message">&firstrun_sync_message;</string>
<string name="firstrun_sync_subtext">&firstrun_sync_subtext;</string>
<string name="firstrun_signin_message">&firstrun_signin_message;</string>
<string name="firstrun_sync_message">&firstrun_sync_message2;</string>
<string name="firstrun_sync_subtext">&firstrun_sync_subtext2;</string>
<string name="firstrun_signin_button">&firstrun_signin_button;</string>
<string name="firstrun_welcome_button_browser">&onboard_start_button_browser;</string>
<string name="firstrun_button_notnow">&firstrun_button_notnow;</string>
<string name="firstrun_button_next">&firstrun_button_next;</string>
<string name="firstrun_tabqueue_title">&firstrun_tabqueue_title;</string>
<string name="firstrun_tabqueue_message_off">&firstrun_tabqueue_message_off;</string>
<string name="firstrun_tabqueue_subtext_off">&firstrun_tabqueue_subtext_off;</string>
<string name="firstrun_tabqueue_message_on">&firstrun_tabqueue_message_on;</string>
<string name="firstrun_tabqueue_subtext_on">&firstrun_tabqueue_subtext_on;</string>
<string name="firstrun_readerview_title">&firstrun_readerview_title;</string>
<string name="firstrun_readerview_message">&firstrun_readerview_message;</string>
<string name="firstrun_readerview_subtext">&firstrun_readerview_subtext;</string>
<string name="firstrun_account_title">&firstrun_account_title;</string>
<string name="firstrun_account_message">&firstrun_account_message;</string>
<string name="firstrun_welcome_restricted">&onboard_start_restricted1;</string>
<string name="bookmarks_title">&bookmarks_title;</string>

View File

@ -4,8 +4,6 @@
%htmlDTD;
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY % securityPrefsDTD SYSTEM "chrome://browser/locale/preferences/security.dtd">
%securityPrefsDTD;
<!ENTITY % aboutRightsDTD SYSTEM "chrome://global/locale/aboutRights.dtd">
%aboutRightsDTD;
]>

View File

@ -130,7 +130,6 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
public void handleRequestSuccess(SyncStorageResponse response) {
final Context context = session.getContext();
final Account account = FirefoxAccounts.getFirefoxAccount(context);
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
// Hang onto the server's last modified timestamp to use
// in X-If-Unmodified-Since for upload.
@ -182,15 +181,17 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
uploadRemoteRecords();
// We will send a push notification later anyway.
if (!isFirstLocalClientRecordUpload) {
if (!isFirstLocalClientRecordUpload && account != null) {
// Notify the clients who got their record written
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
notifyClients(fxAccount, devicesToNotify);
}
return;
}
checkAndUpload();
if (isFirstLocalClientRecordUpload) {
if (isFirstLocalClientRecordUpload && account != null) {
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
notifyAllClients(fxAccount);
}
}

View File

@ -90,7 +90,7 @@
android:layout_marginStart="100dp"
android:layout_marginRight="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:paddingLeft="16dp"
android:paddingStart="16dp"
android:paddingRight="16dp"

View File

@ -53,7 +53,7 @@
<Button
android:id="@+id/button"
style="@style/Widget.Firstrun.Button"
android:background="@drawable/button_background_action_orange_round"
android:background="@drawable/button_background_action_photon_round"
android:layout_gravity="center"
android:layout_marginBottom="30dp"/>

View File

@ -183,6 +183,11 @@ div[collapsed="true"] > .expander + * {
border-radius: 0;
}
#advisory_provider {
color: white;
text-decoration: underline;
}
/* On large screen devices (hopefully a 7+ inch tablet, we already center content (see #errorPageContainer above).
Apply tablet specific styles here */
@media (min-width: 550px) {

View File

@ -797,13 +797,13 @@ public abstract class MetaScanner {
}
if (contentIndex == CONTENT.length && content == null) {
content = Portability.newStringFromBuffer(strBuf, 0, strBufLen
// CPPONLY: , treeBuilder
// CPPONLY: , treeBuilder, false
);
return;
}
if (charsetIndex == CHARSET.length && charset == null) {
charset = Portability.newStringFromBuffer(strBuf, 0, strBufLen
// CPPONLY: , treeBuilder
// CPPONLY: , treeBuilder, false
);
return;
}

View File

@ -40,7 +40,7 @@ public final class Portability {
}
public static String newStringFromBuffer(@NoLength char[] buf, int offset, int length
// CPPONLY: , TreeBuilder treeBuilder
// CPPONLY: , TreeBuilder treeBuilder, boolean maybeAtomize
) {
return new String(buf, offset, length);
}

View File

@ -897,7 +897,7 @@ public class Tokenizer implements Locator {
*/
protected String strBufToString() {
String str = Portability.newStringFromBuffer(strBuf, 0, strBufLen
// CPPONLY: , tokenHandler
// CPPONLY: , tokenHandler, !newAttributesEachTime && attributeName == AttributeName.CLASS
);
clearStrBufAfterUse();
return str;

View File

@ -3293,7 +3293,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
}
charset = Portability.newStringFromBuffer(buffer, start, end
- start
// CPPONLY: , tb
// CPPONLY: , tb, false
);
}
return charset;

View File

@ -755,11 +755,13 @@ nsHtml5MetaScanner::handleAttributeValue()
return;
}
if (contentIndex == CONTENT.length && !content) {
content = nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, treeBuilder);
content = nsHtml5Portability::newStringFromBuffer(
strBuf, 0, strBufLen, treeBuilder, false);
return;
}
if (charsetIndex == CHARSET.length && !charset) {
charset = nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, treeBuilder);
charset = nsHtml5Portability::newStringFromBuffer(
strBuf, 0, strBufLen, treeBuilder, false);
return;
}
if (httpEquivIndex == HTTP_EQUIV.length &&

View File

@ -16,12 +16,30 @@ nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_
return interner->GetAtom(nsDependentSubstring(buf, buf + length));
}
static bool
ContainsWhiteSpace(mozilla::Span<char16_t> aSpan)
{
for (char16_t c : aSpan) {
if (nsContentUtils::IsHTMLWhitespace(c)) {
return true;
}
}
return false;
}
nsHtml5String
nsHtml5Portability::newStringFromBuffer(char16_t* buf,
int32_t offset,
int32_t length,
nsHtml5TreeBuilder* treeBuilder)
nsHtml5TreeBuilder* treeBuilder,
bool maybeAtomize)
{
if (!length) {
return nsHtml5String::EmptyString();
}
if (maybeAtomize && !ContainsWhiteSpace(mozilla::MakeSpan(buf + offset, length))) {
return nsHtml5String::FromAtom(NS_AtomizeMainThread(nsDependentSubstring(buf + offset, length)));
}
return nsHtml5String::FromBuffer(buf + offset, length, treeBuilder);
}

Some files were not shown because too many files have changed in this diff Show More