Merge autoland to m-c, a=merge
MozReview-Commit-ID: Gr2qiJufRRz
|
@ -299,6 +299,7 @@ pref("browser.urlbar.doubleClickSelectsAll", false);
|
|||
// Control autoFill behavior
|
||||
pref("browser.urlbar.autoFill", true);
|
||||
pref("browser.urlbar.autoFill.typed", true);
|
||||
pref("browser.urlbar.speculativeConnect.enabled", true);
|
||||
|
||||
// 0: Match anywhere (e.g., middle of words)
|
||||
// 1: Match on word boundaries and then try matching anywhere
|
||||
|
@ -1141,8 +1142,6 @@ pref("browser.taskbar.lists.tasks.enabled", true);
|
|||
pref("browser.taskbar.lists.refreshInSeconds", 120);
|
||||
#endif
|
||||
|
||||
// The sync engines to use.
|
||||
pref("services.sync.registerEngines", "Bookmarks,Form,History,Password,Prefs,Tab,Addons,ExtensionStorage");
|
||||
// Preferences to be synced by default
|
||||
pref("services.sync.prefs.sync.accessibility.blockautorefresh", true);
|
||||
pref("services.sync.prefs.sync.accessibility.browsewithcaret", true);
|
||||
|
|
|
@ -1312,8 +1312,7 @@ var gBrowserInit = {
|
|||
// have been initialized.
|
||||
Services.obs.notifyObservers(window, "browser-window-before-show");
|
||||
|
||||
gUIDensity.update();
|
||||
gPrefService.addObserver(gUIDensity.prefDomain, gUIDensity);
|
||||
gUIDensity.init();
|
||||
|
||||
let isResistFingerprintingEnabled = gPrefService.getBoolPref("privacy.resistFingerprinting");
|
||||
|
||||
|
@ -1775,7 +1774,7 @@ var gBrowserInit = {
|
|||
|
||||
Services.obs.removeObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
|
||||
|
||||
gPrefService.removeObserver(gUIDensity.prefDomain, gUIDensity);
|
||||
gUIDensity.uninit();
|
||||
|
||||
try {
|
||||
gBrowser.removeProgressListener(window.XULBrowserWindow);
|
||||
|
@ -5456,26 +5455,50 @@ function displaySecurityInfo() {
|
|||
|
||||
// Updates the UI density (for touch and compact mode) based on the uidensity pref.
|
||||
var gUIDensity = {
|
||||
MODE_NORMAL: 0,
|
||||
MODE_COMPACT: 1,
|
||||
MODE_TOUCH: 2,
|
||||
prefDomain: "browser.uidensity",
|
||||
uiDensityPref: "browser.uidensity",
|
||||
autoTouchModePref: "browser.touchmode.auto",
|
||||
|
||||
init() {
|
||||
this.update();
|
||||
gPrefService.addObserver(this.uiDensityPref, this);
|
||||
gPrefService.addObserver(this.autoTouchModePref, this);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
gPrefService.removeObserver(this.uiDensityPref, this);
|
||||
gPrefService.removeObserver(this.autoTouchModePref, this);
|
||||
},
|
||||
|
||||
observe(aSubject, aTopic, aPrefName) {
|
||||
if (aTopic != "nsPref:changed" || aPrefName != this.prefDomain)
|
||||
if (aTopic != "nsPref:changed" ||
|
||||
(aPrefName != this.uiDensityPref &&
|
||||
aPrefName != this.autoTouchModePref)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.update();
|
||||
},
|
||||
|
||||
update() {
|
||||
let mode;
|
||||
getCurrentDensity() {
|
||||
// Automatically override the uidensity to touch in Windows tablet mode.
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "10") &&
|
||||
WindowsUIUtils.inTabletMode &&
|
||||
gPrefService.getBoolPref("browser.touchmode.auto")) {
|
||||
mode = this.MODE_TOUCH;
|
||||
} else {
|
||||
mode = gPrefService.getIntPref(this.prefDomain);
|
||||
gPrefService.getBoolPref(this.autoTouchModePref)) {
|
||||
return { mode: this.MODE_TOUCH, overridden: true };
|
||||
}
|
||||
return { mode: gPrefService.getIntPref(this.uiDensityPref), overridden: false };
|
||||
},
|
||||
|
||||
setCurrentMode(mode) {
|
||||
gPrefService.setIntPref(this.uiDensityPref, mode);
|
||||
},
|
||||
|
||||
update(mode) {
|
||||
if (mode == null) {
|
||||
mode = this.getCurrentDensity().mode;
|
||||
}
|
||||
|
||||
let doc = document.documentElement;
|
||||
|
@ -8176,10 +8199,11 @@ var RestoreLastSessionObserver = {
|
|||
if (SessionStore.canRestoreLastSession &&
|
||||
!PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
if (Services.prefs.getBoolPref("browser.tabs.restorebutton")) {
|
||||
let {restoreTabsButton} = gBrowser.tabContainer;
|
||||
let {restoreTabsButton, restoreTabsButtonWrapperWidth} = gBrowser.tabContainer;
|
||||
let restoreTabsButtonWrapper = restoreTabsButton.parentNode;
|
||||
restoreTabsButtonWrapper.setAttribute("session-exists", "true");
|
||||
gBrowser.tabContainer.updateSessionRestoreVisibility();
|
||||
restoreTabsButton.style.maxWidth = `${restoreTabsButtonWrapperWidth}px`;
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", this);
|
||||
}
|
||||
Services.obs.addObserver(this, "sessionstore-last-session-cleared", true);
|
||||
|
@ -8196,17 +8220,16 @@ var RestoreLastSessionObserver = {
|
|||
},
|
||||
|
||||
removeRestoreButton() {
|
||||
let {restoreTabsButton, restoreTabsButtonWrapperWidth} = gBrowser.tabContainer;
|
||||
let {restoreTabsButton} = gBrowser.tabContainer;
|
||||
let restoreTabsButtonWrapper = restoreTabsButton.parentNode;
|
||||
restoreTabsButtonWrapper.removeAttribute("session-exists");
|
||||
gBrowser.tabContainer.addEventListener("transitionend", function maxWidthTransitionHandler(e) {
|
||||
if (e.propertyName == "max-width") {
|
||||
if (e.target == gBrowser.tabContainer && e.propertyName == "max-width") {
|
||||
gBrowser.tabContainer.updateSessionRestoreVisibility();
|
||||
gBrowser.tabContainer.removeEventListener("transitionend", maxWidthTransitionHandler);
|
||||
}
|
||||
});
|
||||
restoreTabsButton.style.maxWidth = `${restoreTabsButtonWrapperWidth}px`;
|
||||
requestAnimationFrame(() => restoreTabsButton.style.maxWidth = 0);
|
||||
restoreTabsButtonWrapper.removeAttribute("session-exists");
|
||||
restoreTabsButton.style.maxWidth = 0;
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", this);
|
||||
},
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ nsContextMenu.prototype = {
|
|||
pageUrl: this.browser ? this.browser.currentURI.spec : undefined,
|
||||
linkText: this.linkTextStr,
|
||||
linkUrl: this.linkURL,
|
||||
selectionText: this.isTextSelected ? this.selectionInfo.text : undefined,
|
||||
selectionText: this.isTextSelected ? this.selectionInfo.fullText : undefined,
|
||||
frameId: this.frameOuterWindowID,
|
||||
};
|
||||
subject.wrappedJSObject = subject;
|
||||
|
|
|
@ -2160,7 +2160,7 @@
|
|||
"characterSet", "fullZoom", "textZoom", "webProgress",
|
||||
"addProgressListener", "removeProgressListener", "audioPlaybackStarted",
|
||||
"audioPlaybackStopped", "pauseMedia", "stopMedia",
|
||||
"blockMedia", "resumeMedia", "mute", "unmute", "blockedPopups", "lastURI",
|
||||
"resumeMedia", "mute", "unmute", "blockedPopups", "lastURI",
|
||||
"purgeSessionHistory", "stopScroll", "startScroll",
|
||||
"userTypedValue", "userTypedClear", "mediaBlocked"
|
||||
]</field>
|
||||
|
@ -2226,7 +2226,6 @@
|
|||
};
|
||||
};
|
||||
break;
|
||||
case "blockMedia":
|
||||
case "resumeMedia":
|
||||
getter = () => {
|
||||
return () => {
|
||||
|
|
|
@ -110,6 +110,7 @@ support-files =
|
|||
support-files =
|
||||
file_urlbar_edit_dos.html
|
||||
[browser_urlbar_searchsettings.js]
|
||||
[browser_urlbar_search_speculative_connect.js]
|
||||
[browser_urlbar_stop_pending.js]
|
||||
support-files =
|
||||
slow-page.sjs
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
"use strict";
|
||||
|
||||
// This test ensures that we setup a speculative network
|
||||
// connection for autoFilled values.
|
||||
|
||||
let {HttpServer} = Cu.import("resource://testing-common/httpd.js", {});
|
||||
let gHttpServer = null;
|
||||
let gScheme = "http";
|
||||
let gHost = "localhost"; // 'localhost' by default.
|
||||
let gPort = -1;
|
||||
|
||||
add_task(async function setup() {
|
||||
if (!gHttpServer) {
|
||||
gHttpServer = new HttpServer();
|
||||
try {
|
||||
gHttpServer.start(gPort);
|
||||
gPort = gHttpServer.identity.primaryPort;
|
||||
gHttpServer.identity.setPrimary(gScheme, gHost, gPort);
|
||||
} catch (ex) {
|
||||
info("We can't launch our http server successfully.")
|
||||
}
|
||||
}
|
||||
is(gHttpServer.identity.has(gScheme, gHost, gPort), true, "make sure we have this domain listed");
|
||||
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.urlbar.autoFill", true],
|
||||
["browser.urlbar.speculativeConnection.enabled", true],
|
||||
// In mochitest this number is 0 by default but we have to turn it on.
|
||||
["network.http.speculative-parallel-limit", 6],
|
||||
// The http server is using IPv4, so it's better to disable IPv6 to avoid weird
|
||||
// networking problem.
|
||||
["network.dns.disableIPv6", true]],
|
||||
});
|
||||
|
||||
await PlacesTestUtils.addVisits([{
|
||||
uri: `${gScheme}://${gHost}:${gPort}`,
|
||||
title: "test visit for speculative connection",
|
||||
transition: Ci.nsINavHistoryService.TRANSITION_TYPED,
|
||||
}]);
|
||||
|
||||
// Bug 764062 - we can't get port number from autocomplete result, so we have to mock
|
||||
// this function to add it manually.
|
||||
let oldSpeculativeConnect = gURLBar.popup.maybeSetupSpeculativeConnect.bind(gURLBar.popup);
|
||||
gURLBar.popup.maybeSetupSpeculativeConnect = (uriString) => {
|
||||
info(`Original uri is ${uriString}`);
|
||||
let newUriString = uriString.substr(0, uriString.length - 1) +
|
||||
":" + gPort + "/";
|
||||
info(`New uri is ${newUriString}`);
|
||||
oldSpeculativeConnect(newUriString);
|
||||
};
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesTestUtils.clearHistory();
|
||||
gURLBar.popup.maybeSetupSpeculativeConnect = oldSpeculativeConnect;
|
||||
gHttpServer.identity.remove(gScheme, gHost, gPort);
|
||||
gHttpServer.stop(() => {
|
||||
gHttpServer = null;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function autofill_tests() {
|
||||
const test = {
|
||||
search: gHost.substr(0, 2),
|
||||
autofilledValue: `${gHost}/`
|
||||
};
|
||||
|
||||
info(`Searching for '${test.search}'`);
|
||||
await promiseAutocompleteResultPopup(test.search, window, true);
|
||||
is(gURLBar.inputField.value, test.autofilledValue,
|
||||
`Autofilled value is as expected for search '${test.search}'`);
|
||||
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
if (gHttpServer) {
|
||||
is(gHttpServer.connectionNumber, 1,
|
||||
`${gHttpServer.connectionNumber} speculative connection has been setup.`)
|
||||
return gHttpServer.connectionNumber == 1;
|
||||
}
|
||||
return false;
|
||||
}, "Waiting for connection setup");
|
||||
});
|
||||
|
|
@ -2114,6 +2114,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<method name="maybeSetupSpeculativeConnect">
|
||||
<parameter name="aUriString"/>
|
||||
<body><![CDATA[
|
||||
// We shouldn't leak autocomplete result in the private context.
|
||||
if (!Services.prefs.getBoolPref("browser.urlbar.speculativeConnect.enabled") ||
|
||||
this.input.inPrivateContext) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
let uri = makeURI(aUriString);
|
||||
Services.io.speculativeConnect2(uri, gBrowser.contentPrincipal, null);
|
||||
} catch (ex) {
|
||||
// Can't setup speculative connection for this uri string for some
|
||||
// reason, just ignore it.
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="onResultsAdded">
|
||||
<body>
|
||||
<![CDATA[
|
||||
|
@ -2126,6 +2144,20 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||
this.input.controller.setInitiallySelectedIndex(0);
|
||||
this.richlistbox.suppressMenuItemEvent = false;
|
||||
}
|
||||
// If this is the first time we get the result from the current
|
||||
// search, and the result is an "autofill" result, that means it's
|
||||
// the site that user frequently visits. Then we could speculatively
|
||||
// connect to this site as a performance optimization.
|
||||
if (!this.input.gotResultForCurrentQuery &&
|
||||
this.input.mController.matchCount > 0 &&
|
||||
this.input.mController.getStyleAt(0).includes("autofill")) {
|
||||
let uri = this.input.mController.getFinalCompleteValueAt(0);
|
||||
// "http" will be stripped out, but other scheme won't.
|
||||
if (!uri.includes("://")) {
|
||||
uri = "http://" + uri;
|
||||
}
|
||||
this.maybeSetupSpeculativeConnect(uri);
|
||||
}
|
||||
|
||||
// When a result is present the footer should always be visible.
|
||||
this.footer.collapsed = false;
|
||||
|
|
|
@ -45,6 +45,8 @@ const kPrefCustomizationState = "browser.uiCustomization.state";
|
|||
const kPrefCustomizationAutoAdd = "browser.uiCustomization.autoAdd";
|
||||
const kPrefCustomizationDebug = "browser.uiCustomization.debug";
|
||||
const kPrefDrawInTitlebar = "browser.tabs.drawInTitlebar";
|
||||
const kPrefUIDensity = "browser.uidensity";
|
||||
const kPrefAutoTouchMode = "browser.touchmode.auto";
|
||||
|
||||
const kExpectedWindowURL = "chrome://browser/content/browser.xul";
|
||||
|
||||
|
@ -159,6 +161,8 @@ var gUIStateBeforeReset = {
|
|||
uiCustomizationState: null,
|
||||
drawInTitlebar: null,
|
||||
currentTheme: null,
|
||||
uiDensity: null,
|
||||
autoTouchMode: null,
|
||||
};
|
||||
|
||||
var gDefaultPanelPlacements = null;
|
||||
|
@ -2551,6 +2555,8 @@ var CustomizableUIInternal = {
|
|||
try {
|
||||
gUIStateBeforeReset.drawInTitlebar = Services.prefs.getBoolPref(kPrefDrawInTitlebar);
|
||||
gUIStateBeforeReset.uiCustomizationState = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
gUIStateBeforeReset.uiDensity = Services.prefs.getIntPref(kPrefUIDensity);
|
||||
gUIStateBeforeReset.autoTouchMode = Services.prefs.getBoolPref(kPrefAutoTouchMode);
|
||||
gUIStateBeforeReset.currentTheme = LightweightThemeManager.currentTheme;
|
||||
} catch (e) { }
|
||||
|
||||
|
@ -2558,6 +2564,8 @@ var CustomizableUIInternal = {
|
|||
|
||||
Services.prefs.clearUserPref(kPrefCustomizationState);
|
||||
Services.prefs.clearUserPref(kPrefDrawInTitlebar);
|
||||
Services.prefs.clearUserPref(kPrefUIDensity);
|
||||
Services.prefs.clearUserPref(kPrefAutoTouchMode);
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
log.debug("State reset");
|
||||
|
||||
|
@ -2628,6 +2636,8 @@ var CustomizableUIInternal = {
|
|||
let uiCustomizationState = gUIStateBeforeReset.uiCustomizationState;
|
||||
let drawInTitlebar = gUIStateBeforeReset.drawInTitlebar;
|
||||
let currentTheme = gUIStateBeforeReset.currentTheme;
|
||||
let uiDensity = gUIStateBeforeReset.uiDensity;
|
||||
let autoTouchMode = gUIStateBeforeReset.autoTouchMode;
|
||||
|
||||
// Need to clear the previous state before setting the prefs
|
||||
// because pref observers may check if there is a previous UI state.
|
||||
|
@ -2635,6 +2645,8 @@ var CustomizableUIInternal = {
|
|||
|
||||
Services.prefs.setCharPref(kPrefCustomizationState, uiCustomizationState);
|
||||
Services.prefs.setBoolPref(kPrefDrawInTitlebar, drawInTitlebar);
|
||||
Services.prefs.setIntPref(kPrefUIDensity, uiDensity);
|
||||
Services.prefs.setBoolPref(kPrefAutoTouchMode, autoTouchMode);
|
||||
LightweightThemeManager.currentTheme = currentTheme;
|
||||
this.loadSavedState();
|
||||
// If the user just customizes toolbar/titlebar visibility, gSavedState will be null
|
||||
|
@ -2809,6 +2821,16 @@ var CustomizableUIInternal = {
|
|||
}
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(kPrefUIDensity)) {
|
||||
log.debug(kPrefUIDensity + " pref is non-default");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(kPrefAutoTouchMode)) {
|
||||
log.debug(kPrefAutoTouchMode + " pref is non-default");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Services.prefs.prefHasUserValue(kPrefDrawInTitlebar)) {
|
||||
log.debug(kPrefDrawInTitlebar + " pref is non-default");
|
||||
return false;
|
||||
|
@ -3540,7 +3562,9 @@ this.CustomizableUI = {
|
|||
get canUndoReset() {
|
||||
return gUIStateBeforeReset.uiCustomizationState != null ||
|
||||
gUIStateBeforeReset.drawInTitlebar != null ||
|
||||
gUIStateBeforeReset.currentTheme != null;
|
||||
gUIStateBeforeReset.currentTheme != null ||
|
||||
gUIStateBeforeReset.autoTouchMode != null ||
|
||||
gUIStateBeforeReset.uiDensity != null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -1385,6 +1385,98 @@ CustomizeMode.prototype = {
|
|||
this.window.openUILinkIn(getMoreURL, "tab");
|
||||
},
|
||||
|
||||
updateUIDensity(mode) {
|
||||
this.window.gUIDensity.update(mode);
|
||||
},
|
||||
|
||||
setUIDensity(mode) {
|
||||
let win = this.window;
|
||||
let gUIDensity = win.gUIDensity;
|
||||
let currentDensity = gUIDensity.getCurrentDensity();
|
||||
let panel = win.document.getElementById("customization-uidensity-menu");
|
||||
|
||||
Services.prefs.setIntPref(gUIDensity.uiDensityPref, mode);
|
||||
|
||||
// If the user is choosing a different UI density mode while
|
||||
// the mode is overriden to Touch, remove the override.
|
||||
if (currentDensity.overridden) {
|
||||
Services.prefs.setBoolPref(gUIDensity.autoTouchModePref, false);
|
||||
}
|
||||
|
||||
this._onUIChange();
|
||||
panel.hidePopup();
|
||||
},
|
||||
|
||||
resetUIDensity() {
|
||||
this.window.gUIDensity.update();
|
||||
},
|
||||
|
||||
onUIDensityMenuShowing() {
|
||||
let win = this.window;
|
||||
let doc = win.document;
|
||||
let gUIDensity = win.gUIDensity;
|
||||
let currentDensity = gUIDensity.getCurrentDensity();
|
||||
|
||||
let normalButton = doc.getElementById("customization-uidensity-menu-button-normal");
|
||||
normalButton.mode = gUIDensity.MODE_NORMAL;
|
||||
|
||||
let compactButton = doc.getElementById("customization-uidensity-menu-button-compact");
|
||||
compactButton.mode = gUIDensity.MODE_COMPACT;
|
||||
|
||||
let buttons = [normalButton, compactButton];
|
||||
|
||||
let touchButton = doc.getElementById("customization-uidensity-menu-button-touch");
|
||||
// Touch mode can not be enabled in OSX right now.
|
||||
if (touchButton) {
|
||||
touchButton.mode = gUIDensity.MODE_TOUCH;
|
||||
buttons.push(touchButton);
|
||||
}
|
||||
|
||||
// Mark the active mode button.
|
||||
for (let button of buttons) {
|
||||
if (button.mode == currentDensity.mode) {
|
||||
button.setAttribute("aria-checked", "true");
|
||||
button.setAttribute("active", "true");
|
||||
} else {
|
||||
button.removeAttribute("aria-checked");
|
||||
button.removeAttribute("active");
|
||||
}
|
||||
}
|
||||
|
||||
// Add menu items for automatically switching to Touch mode in Windows Tablet Mode,
|
||||
// which is only available in Windows 10.
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
|
||||
let spacer = doc.getElementById("customization-uidensity-touch-spacer");
|
||||
let checkbox = doc.getElementById("customization-uidensity-autotouchmode-checkbox");
|
||||
spacer.removeAttribute("hidden");
|
||||
checkbox.removeAttribute("hidden");
|
||||
|
||||
// Show a hint that the UI density was overridden automatically.
|
||||
if (currentDensity.overridden) {
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/uiDensity.properties");
|
||||
touchButton.setAttribute("acceltext",
|
||||
sb.GetStringFromName("uiDensity.menu-button-touch.acceltext"));
|
||||
} else {
|
||||
touchButton.removeAttribute("acceltext");
|
||||
}
|
||||
|
||||
let autoTouchMode = Services.prefs.getBoolPref(win.gUIDensity.autoTouchModePref);
|
||||
if (autoTouchMode) {
|
||||
checkbox.setAttribute("checked", "true");
|
||||
} else {
|
||||
checkbox.removeAttribute("checked");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateAutoTouchMode(checked) {
|
||||
Services.prefs.setBoolPref("browser.touchmode.auto", checked);
|
||||
// Re-render the menu items since the active mode might have
|
||||
// change because of this.
|
||||
this.onUIDensityMenuShowing();
|
||||
this._onUIChange();
|
||||
},
|
||||
|
||||
onLWThemesMenuShowing(aEvent) {
|
||||
const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
|
||||
const RECENT_LWT_COUNT = 5;
|
||||
|
|
|
@ -51,6 +51,63 @@
|
|||
</hbox>
|
||||
</panel>
|
||||
</button>
|
||||
#ifdef MOZ_PHOTON_THEME
|
||||
<button id="customization-uidensity-button"
|
||||
label="&customizeMode.uidensity;"
|
||||
class="customizationmode-button"
|
||||
type="menu">
|
||||
<panel type="arrow" id="customization-uidensity-menu"
|
||||
onpopupshowing="gCustomizeMode.onUIDensityMenuShowing();"
|
||||
position="topcenter bottomleft"
|
||||
flip="none"
|
||||
role="menu">
|
||||
<menuitem id="customization-uidensity-menu-button-normal"
|
||||
class="menuitem-iconic customization-uidensity-menu-button"
|
||||
role="menuitemradio"
|
||||
label="&customizeMode.uidensity.menuNormal.label;"
|
||||
accesskey="&customizeMode.uidensity.menuNormal.accessKey;"
|
||||
tooltiptext="&customizeMode.uidensity.menuNormal.tooltip;"
|
||||
tabindex="0"
|
||||
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onblur="gCustomizeMode.resetUIDensity();"
|
||||
onmouseout="gCustomizeMode.resetUIDensity();"
|
||||
oncommand="gCustomizeMode.setUIDensity(this.mode);" />
|
||||
<menuitem id="customization-uidensity-menu-button-compact"
|
||||
class="menuitem-iconic customization-uidensity-menu-button"
|
||||
role="menuitemradio"
|
||||
label="&customizeMode.uidensity.menuCompact.label;"
|
||||
accesskey="&customizeMode.uidensity.menuCompact.accessKey;"
|
||||
tooltiptext="&customizeMode.uidensity.menuCompact.tooltip;"
|
||||
tabindex="0"
|
||||
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onblur="gCustomizeMode.resetUIDensity();"
|
||||
onmouseout="gCustomizeMode.resetUIDensity();"
|
||||
oncommand="gCustomizeMode.setUIDensity(this.mode);" />
|
||||
#ifndef XP_MACOSX
|
||||
<menuitem id="customization-uidensity-menu-button-touch"
|
||||
class="menuitem-iconic customization-uidensity-menu-button"
|
||||
role="menuitemradio"
|
||||
label="&customizeMode.uidensity.menuTouch.label;"
|
||||
accesskey="&customizeMode.uidensity.menuTouch.accessKey;"
|
||||
tooltiptext="&customizeMode.uidensity.menuTouch.tooltip;"
|
||||
tabindex="0"
|
||||
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
|
||||
onblur="gCustomizeMode.resetUIDensity();"
|
||||
onmouseout="gCustomizeMode.resetUIDensity();"
|
||||
oncommand="gCustomizeMode.setUIDensity(this.mode);">
|
||||
</menuitem>
|
||||
<spacer hidden="true" id="customization-uidensity-touch-spacer"/>
|
||||
<checkbox id="customization-uidensity-autotouchmode-checkbox"
|
||||
hidden="true"
|
||||
label="&customizeMode.uidensity.autoTouchMode.checkbox.label;"
|
||||
oncommand="gCustomizeMode.updateAutoTouchMode(this.checked)"/>
|
||||
#endif
|
||||
</panel>
|
||||
</button>
|
||||
#endif
|
||||
|
||||
<spacer id="customization-footer-spacer"/>
|
||||
<button id="customization-undo-reset-button"
|
||||
|
|
|
@ -666,11 +666,6 @@
|
|||
key="key_savePage"
|
||||
command="Browser:SavePage"
|
||||
/>
|
||||
<toolbarbutton id="appMenu-page-setup-button"
|
||||
class="subviewbutton"
|
||||
label="&printSetupCmd.label;"
|
||||
command="cmd_pageSetup"
|
||||
/>
|
||||
<toolbarbutton id="appMenu-print-button"
|
||||
class="subviewbutton subviewbutton-iconic"
|
||||
label="&printButton.label;"
|
||||
|
|
|
@ -147,6 +147,7 @@ skip-if = os == "mac"
|
|||
[browser_1161838_inserted_new_default_buttons.js]
|
||||
[browser_bootstrapped_custom_toolbar.js]
|
||||
[browser_customizemode_contextmenu_menubuttonstate.js]
|
||||
[browser_customizemode_uidensity.js]
|
||||
[browser_exit_background_customize_mode.js]
|
||||
[browser_overflow_use_subviews.js]
|
||||
[browser_panel_keyboard_navigation.js]
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const PREF_UI_DENSITY = "browser.uidensity";
|
||||
const PREF_AUTO_TOUCH_MODE = "browser.touchmode.auto";
|
||||
|
||||
async function testModeButton(mode, modePref) {
|
||||
await startCustomizing();
|
||||
|
||||
let win = document.getElementById("main-window");
|
||||
let popupButton = document.getElementById("customization-uidensity-button");
|
||||
let popup = document.getElementById("customization-uidensity-menu");
|
||||
|
||||
// Show the popup.
|
||||
let popupShownPromise = popupShown(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupShownPromise;
|
||||
|
||||
let button = document.getElementById("customization-uidensity-menu-button-" + mode);
|
||||
let normalButton = document.getElementById("customization-uidensity-menu-button-normal");
|
||||
|
||||
is(normalButton.getAttribute("active"), "true",
|
||||
"Normal mode button should be active by default.");
|
||||
|
||||
// Hover over the mode button and wait until the UI density is updated.
|
||||
EventUtils.synthesizeMouseAtCenter(button, { type: "mouseover" });
|
||||
await BrowserTestUtils.waitForAttribute("uidensity", win, mode);
|
||||
|
||||
is(win.getAttribute("uidensity"), mode,
|
||||
`UI Density should be set to ${mode} on ${mode} button hover.`);
|
||||
|
||||
is(Services.prefs.getIntPref(PREF_UI_DENSITY), window.gUIDensity.MODE_NORMAL,
|
||||
`UI Density pref should still be set to normal on ${mode} button hover.`);
|
||||
|
||||
// Hover the normal button again and check that the UI density reset to normal.
|
||||
EventUtils.synthesizeMouseAtCenter(normalButton, { type: "mouseover" });
|
||||
await BrowserTestUtils.waitForCondition(() => !win.hasAttribute("uidensity"));
|
||||
|
||||
ok(!win.hasAttribute("uidensity"),
|
||||
`UI Density should be reset when no longer hovering the ${mode} button.`);
|
||||
|
||||
// Select the custom UI density and wait for the popup to be hidden.
|
||||
let popupHiddenPromise = popupHidden(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(button, {});
|
||||
await popupHiddenPromise;
|
||||
|
||||
// Check that the click permanently changed the UI density.
|
||||
is(win.getAttribute("uidensity"), mode,
|
||||
`UI Density should be set to ${mode} on ${mode} button click.`);
|
||||
is(Services.prefs.getIntPref(PREF_UI_DENSITY), modePref,
|
||||
`UI Density pref should be set to ${mode} when clicking the ${mode} button.`);
|
||||
|
||||
// Open the popup again.
|
||||
popupShownPromise = popupShown(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupShownPromise;
|
||||
|
||||
// Check that the button is still active after opening and closing the popup.
|
||||
is(button.getAttribute("active"), "true", `${mode} mode button should be active.`);
|
||||
|
||||
// Hide the popup again.
|
||||
popupHiddenPromise = popupHidden(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupHiddenPromise;
|
||||
|
||||
// Check that the button is still active after re-opening customize mode.
|
||||
await endCustomizing();
|
||||
await startCustomizing();
|
||||
|
||||
popupShownPromise = popupShown(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupShownPromise;
|
||||
|
||||
is(button.getAttribute("active"), "true",
|
||||
`${mode} mode button should be active after entering and exiting customize mode.`);
|
||||
|
||||
// Click the normal button and check that the density is reset.
|
||||
popupHiddenPromise = popupHidden(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(normalButton, {});
|
||||
await popupHiddenPromise;
|
||||
|
||||
ok(!win.hasAttribute("uidensity"),
|
||||
"UI Density should be reset when clicking the normal button.");
|
||||
|
||||
is(Services.prefs.getIntPref(PREF_UI_DENSITY), window.gUIDensity.MODE_NORMAL,
|
||||
"UI Density pref should be set to normal.");
|
||||
|
||||
// Show the popup and click on the mode button again to test the
|
||||
// reset default feature.
|
||||
popupShownPromise = popupShown(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupShownPromise;
|
||||
|
||||
popupHiddenPromise = popupHidden(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(button, {});
|
||||
await popupHiddenPromise;
|
||||
|
||||
is(win.getAttribute("uidensity"), mode,
|
||||
`UI Density should be set to ${mode} on ${mode} button click.`);
|
||||
|
||||
is(Services.prefs.getIntPref(PREF_UI_DENSITY), modePref,
|
||||
`UI Density pref should be set to ${mode} when clicking the ${mode} button.`);
|
||||
|
||||
await gCustomizeMode.reset();
|
||||
|
||||
ok(!win.hasAttribute("uidensity"),
|
||||
"UI Density should be reset when clicking the normal button.");
|
||||
|
||||
is(Services.prefs.getIntPref(PREF_UI_DENSITY), window.gUIDensity.MODE_NORMAL,
|
||||
"UI Density pref should be set to normal.");
|
||||
|
||||
await endCustomizing();
|
||||
}
|
||||
|
||||
add_task(async function test_compact_mode_button() {
|
||||
if (!AppConstants.MOZ_PHOTON_THEME) {
|
||||
ok(true, "Skipping test because Photon is not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
await testModeButton("compact", window.gUIDensity.MODE_COMPACT);
|
||||
});
|
||||
|
||||
add_task(async function test_touch_mode_button() {
|
||||
if (!AppConstants.MOZ_PHOTON_THEME) {
|
||||
ok(true, "Skipping test because Photon is not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
// OSX doesn't get touch mode for now.
|
||||
if (AppConstants.platform == "macosx") {
|
||||
is(document.getElementById("customization-uidensity-menu-button-touch"), null,
|
||||
"There's no touch option on Mac OSX");
|
||||
return;
|
||||
}
|
||||
|
||||
await testModeButton("touch", window.gUIDensity.MODE_TOUCH);
|
||||
|
||||
// Test the checkbox for automatic Touch Mode transition
|
||||
// in Windows 10 Tablet Mode.
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
|
||||
await startCustomizing();
|
||||
|
||||
let popupButton = document.getElementById("customization-uidensity-button");
|
||||
let popup = document.getElementById("customization-uidensity-menu");
|
||||
let popupShownPromise = popupShown(popup);
|
||||
EventUtils.synthesizeMouseAtCenter(popupButton, {});
|
||||
await popupShownPromise;
|
||||
|
||||
let checkbox = document.getElementById("customization-uidensity-autotouchmode-checkbox");
|
||||
ok(checkbox.checked, "Checkbox should be checked by default");
|
||||
|
||||
// Test toggling the checkbox.
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {});
|
||||
is(Services.prefs.getBoolPref(PREF_AUTO_TOUCH_MODE), false,
|
||||
"Automatic Touch Mode is off when the checkbox is unchecked.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {});
|
||||
is(Services.prefs.getBoolPref(PREF_AUTO_TOUCH_MODE), true,
|
||||
"Automatic Touch Mode is on when the checkbox is checked.");
|
||||
|
||||
// Test reset to defaults.
|
||||
EventUtils.synthesizeMouseAtCenter(checkbox, {});
|
||||
is(Services.prefs.getBoolPref(PREF_AUTO_TOUCH_MODE), false,
|
||||
"Automatic Touch Mode is off when the checkbox is unchecked.");
|
||||
|
||||
await gCustomizeMode.reset();
|
||||
is(Services.prefs.getBoolPref(PREF_AUTO_TOUCH_MODE), true,
|
||||
"Automatic Touch Mode is on when the checkbox is checked.");
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function cleanup() {
|
||||
await endCustomizing();
|
||||
|
||||
Services.prefs.clearUserPref(PREF_UI_DENSITY);
|
||||
Services.prefs.clearUserPref(PREF_AUTO_TOUCH_MODE);
|
||||
});
|
|
@ -193,7 +193,7 @@ var gMenuBuilder = {
|
|||
let label = item.title;
|
||||
if (label) {
|
||||
if (contextData.isTextSelected && label.indexOf("%s") > -1) {
|
||||
let selection = contextData.selectionText;
|
||||
let selection = contextData.selectionText.trim();
|
||||
// The rendering engine will truncate the title if it's longer than 64 characters.
|
||||
// But if it makes sense let's try truncate selection text only, to handle cases like
|
||||
// 'look up "%s" in MyDictionary' more elegantly.
|
||||
|
|
|
@ -59,6 +59,13 @@ add_task(async function() {
|
|||
},
|
||||
|
||||
background: async function() {
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
if (msg == "removeall") {
|
||||
browser.contextMenus.removeAll();
|
||||
browser.test.sendMessage("removed");
|
||||
}
|
||||
});
|
||||
|
||||
// A generic onclick callback function.
|
||||
function genericOnClick(info, tab) {
|
||||
browser.test.sendMessage("onclick", {info, tab});
|
||||
|
@ -86,10 +93,7 @@ add_task(async function() {
|
|||
if (context == "selection") {
|
||||
browser.contextMenus.update("ext-selection", {
|
||||
title: "selection is: '%s'",
|
||||
onclick: (info, tab) => {
|
||||
browser.contextMenus.removeAll();
|
||||
genericOnClick(info, tab);
|
||||
},
|
||||
onclick: genericOnClick,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +294,7 @@ add_task(async function() {
|
|||
expectedClickInfo = {
|
||||
menuItemId: "ext-selection",
|
||||
pageUrl: PAGE,
|
||||
selectionText: "just some text 1234567890123456789012345678901234567890123456789012345678901234567890123456789012",
|
||||
selectionText: " just some text 1234567890123456789012345678901234567890123456789012345678901234567890123456789012",
|
||||
};
|
||||
|
||||
result = await extension.awaitMessage("onclick");
|
||||
|
@ -298,6 +302,72 @@ add_task(async function() {
|
|||
result = await extension.awaitMessage("browser.contextMenus.onClicked");
|
||||
checkClickInfo(result);
|
||||
|
||||
// Select a lot of text
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, { }, function* (arg) {
|
||||
let doc = content.document;
|
||||
let range = doc.createRange();
|
||||
let selection = content.getSelection();
|
||||
selection.removeAllRanges();
|
||||
let textNode = doc.getElementById("longtext").firstChild;
|
||||
range.setStart(textNode, 0);
|
||||
range.setEnd(textNode, textNode.length);
|
||||
selection.addRange(range);
|
||||
});
|
||||
|
||||
// Bring up context menu again
|
||||
extensionMenuRoot = await openExtensionContextMenu("#longtext");
|
||||
|
||||
// Check some menu items
|
||||
items = extensionMenuRoot.getElementsByAttribute("label", "selection is: 'Sed ut perspiciatis unde omnis iste natus err...'");
|
||||
is(items.length, 1, `contextMenu item for longtext selection was found (context=selection)`);
|
||||
await closeExtensionContextMenu(items[0]);
|
||||
|
||||
expectedClickInfo = {
|
||||
menuItemId: "ext-selection",
|
||||
pageUrl: PAGE,
|
||||
};
|
||||
|
||||
result = await extension.awaitMessage("onclick");
|
||||
checkClickInfo(result);
|
||||
result = await extension.awaitMessage("browser.contextMenus.onClicked");
|
||||
checkClickInfo(result);
|
||||
ok(result.info.selectionText.endsWith("quo voluptas nulla pariatur?"), "long text selection worked");
|
||||
|
||||
|
||||
// Select a lot of text, excercise the nsIDOMNSEditableElement code path in
|
||||
// the Browser:GetSelection handler.
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, { }, function(arg) {
|
||||
let doc = content.document;
|
||||
let node = doc.getElementById("editabletext");
|
||||
// content.js handleContentContextMenu fails intermittently without focus.
|
||||
node.focus();
|
||||
node.selectionStart = 0;
|
||||
node.selectionEnd = 844;
|
||||
});
|
||||
|
||||
// Bring up context menu again
|
||||
extensionMenuRoot = await openExtensionContextMenu("#editabletext");
|
||||
|
||||
// Check some menu items
|
||||
items = extensionMenuRoot.getElementsByAttribute("label", "editable");
|
||||
is(items.length, 1, "contextMenu item for text input element was found (context=editable)");
|
||||
await closeExtensionContextMenu(items[0]);
|
||||
|
||||
expectedClickInfo = {
|
||||
menuItemId: "ext-editable",
|
||||
editable: true,
|
||||
pageUrl: PAGE,
|
||||
};
|
||||
|
||||
result = await extension.awaitMessage("onclick");
|
||||
checkClickInfo(result);
|
||||
result = await extension.awaitMessage("browser.contextMenus.onClicked");
|
||||
checkClickInfo(result);
|
||||
ok(result.info.selectionText.endsWith("perferendis doloribus asperiores repellat."), "long text selection worked");
|
||||
|
||||
extension.sendMessage("removeall");
|
||||
await extension.awaitMessage("removed");
|
||||
|
||||
let contentAreaContextMenu = await openContextMenu("#img1");
|
||||
items = contentAreaContextMenu.getElementsByAttribute("ext-type", "top-level-menu");
|
||||
is(items.length, 0, "top level item was not found (after removeAll()");
|
||||
|
|
|
@ -155,10 +155,13 @@ add_task(async function test_url() {
|
|||
// Create a new tab for testing update.
|
||||
browser.tabs.create({}, function(tab) {
|
||||
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
|
||||
// Check callback
|
||||
browser.test.assertEq(tabId, tab.id, "Check tab id");
|
||||
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
|
||||
if ("url" in changeInfo) {
|
||||
// When activity stream is enabled, about:newtab runs in the content process
|
||||
// which causes some timing issues for onUpdated. So if we encounter
|
||||
// about:newtab, return early and continue waiting for about:blank.
|
||||
if (changeInfo.url === "about:newtab") {
|
||||
return;
|
||||
}
|
||||
browser.test.assertEq("about:blank", changeInfo.url,
|
||||
"Check changeInfo.url");
|
||||
browser.tabs.onUpdated.removeListener(onUpdated);
|
||||
|
@ -166,6 +169,9 @@ add_task(async function test_url() {
|
|||
browser.tabs.remove(tabId);
|
||||
browser.test.notifyPass("finish");
|
||||
}
|
||||
// Check callback
|
||||
browser.test.assertEq(tabId, tab.id, "Check tab id");
|
||||
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
|
||||
});
|
||||
browser.tabs.update(tab.id, {url: "about:blank"});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
@ -20,6 +21,20 @@
|
|||
<input type="text" id="edit-me"><br>
|
||||
<input type="password" id="password">
|
||||
</p>
|
||||
<iframe id="frame" src="context_frame.html"/>
|
||||
<iframe id="frame" src="context_frame.html"></iframe>
|
||||
<p id="longtext">Sed ut perspiciatis unde omnis iste natus error sit
|
||||
voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque
|
||||
ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta
|
||||
sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
|
||||
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem
|
||||
sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit
|
||||
amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora
|
||||
incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad
|
||||
minima veniam, quis nostrum exercitationem ullam corporis suscipit
|
||||
laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum
|
||||
iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae
|
||||
consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
|
||||
|
||||
<input id="editabletext" type="text" value="At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat." />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -666,7 +666,10 @@ add_task(async function checkUndoVisitsState() {
|
|||
|
||||
add_task(async function checkHistoryRemovalCompletion() {
|
||||
AutoMigrate._errorMap = {bookmarks: 0, visits: 0, logins: 0};
|
||||
await AutoMigrate._removeSomeVisits([{url: "http://www.example.com/", limit: -1}]);
|
||||
await AutoMigrate._removeSomeVisits([{url: "http://www.example.com/",
|
||||
first: 0,
|
||||
last: PlacesUtils.toPRTime(new Date()),
|
||||
limit: -1}]);
|
||||
ok(true, "Removing visits should complete even if removing some visits failed.");
|
||||
Assert.equal(AutoMigrate._errorMap.visits, 1, "Should have logged the error for visits.");
|
||||
|
||||
|
|
|
@ -3598,9 +3598,7 @@ var SessionStoreInternal = {
|
|||
tab.toggleMuteAudio(tabData.muteReason);
|
||||
}
|
||||
|
||||
if (tabData.mediaBlocked) {
|
||||
browser.blockMedia();
|
||||
} else {
|
||||
if (!tabData.mediaBlocked) {
|
||||
browser.resumeMedia();
|
||||
}
|
||||
|
||||
|
|
|
@ -481,6 +481,13 @@ if (typeof Mozilla == "undefined") {
|
|||
* @property {String} distribution - Contains the distributionId property. This value will be
|
||||
* "default" in most cases but can differ for repack or
|
||||
* funnelcake builds. Since Fx48
|
||||
* @property {Number} profileCreatedWeeksAgo - The number of weeks since the profile was created,
|
||||
* starting from 0 for profiles dating less than
|
||||
* seven days old. Since Fx56.
|
||||
* @property {Number} profileResetWeeksAgo - The number of weeks since the profile was last reset,
|
||||
* starting from 0 for profiles reset less than seven
|
||||
* days ago. If the profile has never been reset it
|
||||
* returns null. Since Fx56.
|
||||
* @property {String} version - Version string e.g. "48.0a2"
|
||||
* @since 35
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
|
|||
"resource:///modules/BrowserUITelemetry.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
|
||||
"resource://gre/modules/ProfileAge.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ReaderParent",
|
||||
"resource:///modules/ReaderParent.jsm");
|
||||
|
||||
|
@ -1483,43 +1485,7 @@ this.UITour = {
|
|||
getConfiguration(aMessageManager, aWindow, aConfiguration, aCallbackID) {
|
||||
switch (aConfiguration) {
|
||||
case "appinfo":
|
||||
let props = ["defaultUpdateChannel", "version"];
|
||||
let appinfo = {};
|
||||
props.forEach(property => appinfo[property] = Services.appinfo[property]);
|
||||
|
||||
// Identifier of the partner repack, as stored in preference "distribution.id"
|
||||
// and included in Firefox and other update pings. Note this is not the same as
|
||||
// Services.appinfo.distributionID (value of MOZ_DISTRIBUTION_ID is set at build time).
|
||||
let distribution =
|
||||
Services.prefs.getDefaultBranch("distribution.").getCharPref("id", "default");
|
||||
appinfo["distribution"] = distribution;
|
||||
|
||||
let isDefaultBrowser = null;
|
||||
try {
|
||||
let shell = aWindow.getShellService();
|
||||
if (shell) {
|
||||
isDefaultBrowser = shell.isDefaultBrowser(false);
|
||||
}
|
||||
} catch (e) {}
|
||||
appinfo["defaultBrowser"] = isDefaultBrowser;
|
||||
|
||||
let canSetDefaultBrowserInBackground = true;
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2") ||
|
||||
AppConstants.isPlatformAndVersionAtLeast("macosx", "10.10")) {
|
||||
canSetDefaultBrowserInBackground = false;
|
||||
} else if (AppConstants.platform == "linux") {
|
||||
// The ShellService may not exist on some versions of Linux.
|
||||
try {
|
||||
aWindow.getShellService();
|
||||
} catch (e) {
|
||||
canSetDefaultBrowserInBackground = null;
|
||||
}
|
||||
}
|
||||
|
||||
appinfo["canSetDefaultBrowserInBackground"] =
|
||||
canSetDefaultBrowserInBackground;
|
||||
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, appinfo);
|
||||
this.getAppInfo(aMessageManager, aWindow, aCallbackID);
|
||||
break;
|
||||
case "availableTargets":
|
||||
this.getAvailableTargets(aMessageManager, aWindow, aCallbackID);
|
||||
|
@ -1576,6 +1542,64 @@ this.UITour = {
|
|||
}
|
||||
},
|
||||
|
||||
getAppInfo(aMessageManager, aWindow, aCallbackID) {
|
||||
(async() => {
|
||||
let props = ["defaultUpdateChannel", "version"];
|
||||
let appinfo = {};
|
||||
props.forEach(property => appinfo[property] = Services.appinfo[property]);
|
||||
|
||||
// Identifier of the partner repack, as stored in preference "distribution.id"
|
||||
// and included in Firefox and other update pings. Note this is not the same as
|
||||
// Services.appinfo.distributionID (value of MOZ_DISTRIBUTION_ID is set at build time).
|
||||
let distribution =
|
||||
Services.prefs.getDefaultBranch("distribution.").getCharPref("id", "default");
|
||||
appinfo["distribution"] = distribution;
|
||||
|
||||
let isDefaultBrowser = null;
|
||||
try {
|
||||
let shell = aWindow.getShellService();
|
||||
if (shell) {
|
||||
isDefaultBrowser = shell.isDefaultBrowser(false);
|
||||
}
|
||||
} catch (e) {}
|
||||
appinfo["defaultBrowser"] = isDefaultBrowser;
|
||||
|
||||
let canSetDefaultBrowserInBackground = true;
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2") ||
|
||||
AppConstants.isPlatformAndVersionAtLeast("macosx", "10.10")) {
|
||||
canSetDefaultBrowserInBackground = false;
|
||||
} else if (AppConstants.platform == "linux") {
|
||||
// The ShellService may not exist on some versions of Linux.
|
||||
try {
|
||||
aWindow.getShellService();
|
||||
} catch (e) {
|
||||
canSetDefaultBrowserInBackground = null;
|
||||
}
|
||||
}
|
||||
|
||||
appinfo["canSetDefaultBrowserInBackground"] =
|
||||
canSetDefaultBrowserInBackground;
|
||||
|
||||
// Expose Profile creation and last reset dates in weeks.
|
||||
const ONE_WEEK = 7 * 24 * 60 * 60 * 1000;
|
||||
let profileAge = new ProfileAge(null, null);
|
||||
let createdDate = await profileAge.created;
|
||||
let resetDate = await profileAge.reset;
|
||||
let createdWeeksAgo = Math.floor((Date.now() - createdDate) / ONE_WEEK);
|
||||
let resetWeeksAgo = null;
|
||||
if (resetDate) {
|
||||
resetWeeksAgo = Math.floor((Date.now() - resetDate) / ONE_WEEK);
|
||||
}
|
||||
appinfo["profileCreatedWeeksAgo"] = createdWeeksAgo;
|
||||
appinfo["profileResetWeeksAgo"] = resetWeeksAgo;
|
||||
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, appinfo);
|
||||
})().catch(err => {
|
||||
log.error(err);
|
||||
this.sendPageCallback(aMessageManager, aCallbackID, {});
|
||||
})
|
||||
},
|
||||
|
||||
getAvailableTargets(aMessageManager, aChromeWindow, aCallbackID) {
|
||||
(async () => {
|
||||
let window = aChromeWindow;
|
||||
|
|
|
@ -8,6 +8,8 @@ var gContentAPI;
|
|||
var gContentWindow;
|
||||
|
||||
Components.utils.import("resource://testing-common/TelemetryArchiveTesting.jsm", this);
|
||||
Components.utils.import("resource://gre/modules/ProfileAge.jsm", this);
|
||||
|
||||
|
||||
function test() {
|
||||
UITourTest();
|
||||
|
@ -303,6 +305,21 @@ var tests = [
|
|||
});
|
||||
});
|
||||
},
|
||||
function test_getConfigurationProfileAge(done) {
|
||||
gContentAPI.getConfiguration("appinfo", (result) => {
|
||||
ok(typeof(result.profileCreatedWeeksAgo) === "number", "profileCreatedWeeksAgo should be number.");
|
||||
ok(result.profileResetWeeksAgo === null, "profileResetWeeksAgo should be null.");
|
||||
|
||||
// Set profile reset date to 15 days ago.
|
||||
let profileAccessor = new ProfileAge();
|
||||
profileAccessor.recordProfileReset(Date.now() - (15 * 24 * 60 * 60 * 1000));
|
||||
gContentAPI.getConfiguration("appinfo", (result2) => {
|
||||
ok(typeof(result2.profileResetWeeksAgo) === "number", "profileResetWeeksAgo should be number.");
|
||||
is(result2.profileResetWeeksAgo, 2, "profileResetWeeksAgo should be 2.");
|
||||
done();
|
||||
});
|
||||
});
|
||||
},
|
||||
function test_addToolbarButton(done) {
|
||||
let placement = CustomizableUI.getPlacementOfWidget("panic-button");
|
||||
is(placement, null, "default UI has panic button in the palette");
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
[
|
||||
{
|
||||
"version": "gcc 4.9.4 + PR64905",
|
||||
"size": 101297752,
|
||||
"digest": "42aa2e3fdd232b5e390472a788e7f7db71a1fee4221e260b6cb58c9a1d73e6cdd10afcbac137f7844290169cd6b561b424ecc92b159e9726b0ad5de3f478a8be",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gcc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "clang 4.0.1 gecko build for linux",
|
||||
"size": 215309284,
|
||||
"visibility": "public",
|
||||
"digest": "8f6d386ca1d4606526dd24f366b1dbc1914c6c6d7f54c69c2a2ca0e7cfabe641c1168952d606295feffa9f38ad687084de5efb1e80be3ed2f431ac91de80039b",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.18.0 (03fc9d622 2017-06-06) repack",
|
||||
"size": 146886764,
|
||||
"digest": "e03eeebd4acc593369d5635a059f55a6beed2d2fb839a8c196ccc735a246620d3285a15c17ab34fa8bcf9dd57dd25f735d4ef3eb2fc3be672bbde62342823f1e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12072532,
|
||||
"digest": "3915f8ec396c56a8a92e6f9695b70f09ce9d1582359d1258e37e3fd43a143bc974410e4cfc27f500e095f34a8956206e0ebf799b7287f0f38def0d5e34ed71c9",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
|
@ -51,6 +51,29 @@ const CONTENT = {
|
|||
popupIconURL: "chrome://formautofill/content/icon-address-save.svg",
|
||||
},
|
||||
},
|
||||
update: {
|
||||
notificationId: "autofill-address",
|
||||
message: GetStringFromName("updateAddressMessage"),
|
||||
anchor: {
|
||||
id: "autofill-address-notification-icon",
|
||||
URL: "chrome://formautofill/content/formfill-anchor.svg",
|
||||
tooltiptext: GetStringFromName("openAutofillMessagePanel"),
|
||||
},
|
||||
mainAction: {
|
||||
label: GetStringFromName("updateAddressLabel"),
|
||||
accessKey: "U",
|
||||
callbackState: "update",
|
||||
},
|
||||
secondaryActions: [{
|
||||
label: GetStringFromName("createAddressLabel"),
|
||||
accessKey: "C",
|
||||
callbackState: "create",
|
||||
}],
|
||||
options: {
|
||||
persistWhileVisible: true,
|
||||
popupIconURL: "chrome://formautofill/content/icon-address-update.svg",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let FormAutofillDoorhanger = {
|
||||
|
|
|
@ -280,7 +280,25 @@ FormAutofillParent.prototype = {
|
|||
|
||||
if (address.guid) {
|
||||
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record)) {
|
||||
// TODO: Show update doorhanger(bug 1303513) and set probe(bug 990200)
|
||||
FormAutofillDoorhanger.show(target, "update").then((state) => {
|
||||
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record);
|
||||
switch (state) {
|
||||
case "create":
|
||||
if (!changedGUIDs.length) {
|
||||
changedGUIDs.push(this.profileStorage.addresses.add(address.record));
|
||||
}
|
||||
break;
|
||||
case "update":
|
||||
if (!changedGUIDs.length) {
|
||||
this.profileStorage.addresses.update(address.guid, address.record);
|
||||
changedGUIDs.push(address.guid);
|
||||
} else {
|
||||
this.profileStorage.addresses.remove(address.guid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
changedGUIDs.forEach(guid => this.profileStorage.addresses.notifyUsed(guid));
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.profileStorage.addresses.notifyUsed(address.guid);
|
||||
|
|
|
@ -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" viewBox="0 0 32 32">
|
||||
<path fill="#999899" d="M22 13.7H9.4c-.6 0-1.2.5-1.2 1.2 0 .6.5 1.2 1.2 1.2H22c.6 0 1.2-.5 1.2-1.2s-.6-1.2-1.2-1.2zM6.1 26.6V5.5c0-.8.7-1.5 1.5-1.5h16c.9 0 1.5.6 1.5 1.5V16h2V3.8c0-1-.7-1.8-1.8-1.8H5.9c-1 0-1.8.8-1.8 1.8v24.5c0 1 .8 1.7 1.8 1.7h9.3v-2H7.6c-.8 0-1.5-.6-1.5-1.4zm9.8-7.5H9.4c-.6 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h6.5c.6 0 1.2-.5 1.2-1.2s-.6-1.2-1.2-1.2zM22 7.8H9.4c-.6 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2H22c.6 0 1.2-.5 1.2-1.2s-.6-1.2-1.2-1.2zm-5.7 16l4.4-4.3c.2-.2.5-.3.8-.3s.6.1.8.3l4.4 4.3c.5.5.3.8-.3.8h-2.6v4.7c0 .4-.4.8-.8.8h-3c-.4 0-.8-.4-.8-.8v-4.7h-2.5c-.7 0-.8-.4-.4-.8z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 874 B |
|
@ -10,6 +10,9 @@ viewAutofillOptionsLink = View Form Autofill Options
|
|||
changeAutofillOptions = Change Form Autofill Options
|
||||
viewAutofillOptionsLinkOSX = View Form Autofill Preferences
|
||||
changeAutofillOptionsOSX = Change Form Autofill Preferences
|
||||
updateAddressMessage = Would you like to update your address with this new information?
|
||||
createAddressLabel = Create New Address
|
||||
updateAddressLabel = Update Address
|
||||
openAutofillMessagePanel = Open Form Autofill message panel
|
||||
autocompleteFooterOption = Form Autofill Options
|
||||
autocompleteFooterOptionShort = Options
|
||||
|
|
|
@ -11,3 +11,4 @@ support-files =
|
|||
[browser_privacyPreferences.js]
|
||||
[browser_manageProfilesDialog.js]
|
||||
[browser_submission_in_private_mode.js]
|
||||
[browser_update_doorhanger.js]
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
"use strict";
|
||||
|
||||
const FORM_URL = "http://mochi.test:8888/browser/browser/extensions/formautofill/test/browser/autocomplete_basic.html";
|
||||
|
||||
add_task(async function test_update_address() {
|
||||
await saveAddress(TEST_ADDRESS_1);
|
||||
let addresses = await getAddresses();
|
||||
is(addresses.length, 1, "1 address in storage");
|
||||
|
||||
await BrowserTestUtils.withNewTab({gBrowser, url: FORM_URL},
|
||||
async function(browser) {
|
||||
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
|
||||
"popupshown");
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
content.document.querySelector("form #organization").focus();
|
||||
});
|
||||
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await expectPopupOpen(browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
|
||||
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
let form = content.document.getElementById("form");
|
||||
let org = form.querySelector("#organization");
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
org.value = "Mozilla";
|
||||
|
||||
// Wait 1000ms before submission to make sure the input value applied
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
form.querySelector("input[type=submit]").click();
|
||||
});
|
||||
|
||||
await promiseShown;
|
||||
let notificationElement = PopupNotifications.panel.firstChild;
|
||||
notificationElement.button.click();
|
||||
}
|
||||
);
|
||||
|
||||
addresses = await getAddresses();
|
||||
is(addresses.length, 1, "Still 1 address in storage");
|
||||
is(addresses[0].organization, "Mozilla", "Verify the organization field");
|
||||
});
|
||||
|
||||
add_task(async function test_create_new_address() {
|
||||
let addresses = await getAddresses();
|
||||
is(addresses.length, 1, "1 address in storage");
|
||||
|
||||
await BrowserTestUtils.withNewTab({gBrowser, url: FORM_URL},
|
||||
async function(browser) {
|
||||
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
|
||||
"popupshown");
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
content.document.querySelector("form #tel").focus();
|
||||
});
|
||||
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await expectPopupOpen(browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
|
||||
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
let form = content.document.getElementById("form");
|
||||
let tel = form.querySelector("#tel");
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
tel.value = "+1-234-567-890";
|
||||
|
||||
// Wait 1000ms before submission to make sure the input value applied
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
form.querySelector("input[type=submit]").click();
|
||||
});
|
||||
|
||||
await promiseShown;
|
||||
let notificationElement = PopupNotifications.panel.firstChild;
|
||||
notificationElement.secondaryButton.click();
|
||||
}
|
||||
);
|
||||
|
||||
addresses = await getAddresses();
|
||||
is(addresses.length, 2, "2 addresses in storage");
|
||||
is(addresses[1].tel, "+1-234-567-890", "Verify the tel field");
|
||||
});
|
||||
|
||||
add_task(async function test_create_new_address_merge() {
|
||||
let addresses = await getAddresses();
|
||||
is(addresses.length, 2, "2 address in storage");
|
||||
|
||||
await BrowserTestUtils.withNewTab({gBrowser, url: FORM_URL},
|
||||
async function(browser) {
|
||||
let promiseShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
|
||||
"popupshown");
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
content.document.querySelector("form #tel").focus();
|
||||
});
|
||||
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await expectPopupOpen(browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, browser);
|
||||
await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, browser);
|
||||
|
||||
// Choose the latest address and revert to the original phone number
|
||||
await ContentTask.spawn(browser, null, async function() {
|
||||
let form = content.document.getElementById("form");
|
||||
let tel = form.querySelector("#tel");
|
||||
tel.value = "+1 617 253 5702";
|
||||
|
||||
// Wait 1000ms before submission to make sure the input value applied
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
form.querySelector("input[type=submit]").click();
|
||||
});
|
||||
|
||||
await promiseShown;
|
||||
let notificationElement = PopupNotifications.panel.firstChild;
|
||||
notificationElement.secondaryButton.click();
|
||||
}
|
||||
);
|
||||
|
||||
addresses = await getAddresses();
|
||||
is(addresses.length, 2, "Still 2 addresses in storage");
|
||||
});
|
|
@ -99,6 +99,26 @@ add_task(async function new_address_submitted_and_merged() {
|
|||
delete expectedAddresses[0].timesUsed;
|
||||
});
|
||||
|
||||
// Submit an updated autofill address and merge.
|
||||
add_task(async function check_storage_after_form_submitted() {
|
||||
document.querySelector("form").reset();
|
||||
// Add country to second address in storage
|
||||
await setInput("#country", "US");
|
||||
TEST_ADDRESSES[1].country = "US";
|
||||
|
||||
await setInput("#organization", "Moz");
|
||||
doKey("down");
|
||||
await expectPopup();
|
||||
doKey("down");
|
||||
doKey("return");
|
||||
clickOnElement("input[type=submit]");
|
||||
|
||||
let expectedAddresses = TEST_ADDRESSES.slice(0);
|
||||
await onAddressChanged("merge");
|
||||
let matching = await checkAddresses(expectedAddresses);
|
||||
ok(matching, "Updated address merged as expected");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
|
До Ширина: | Высота: | Размер: 65 KiB После Ширина: | Высота: | Размер: 66 KiB |
До Ширина: | Высота: | Размер: 71 KiB После Ширина: | Высота: | Размер: 91 KiB |
До Ширина: | Высота: | Размер: 10 KiB После Ширина: | Высота: | Размер: 16 KiB |
До Ширина: | Высота: | Размер: 52 KiB После Ширина: | Высота: | Размер: 51 KiB |
До Ширина: | Высота: | Размер: 20 KiB После Ширина: | Высота: | Размер: 13 KiB |
До Ширина: | Высота: | Размер: 8.1 KiB После Ширина: | Высота: | Размер: 645 B |
До Ширина: | Высота: | Размер: 7.5 KiB После Ширина: | Высота: | Размер: 645 B |
До Ширина: | Высота: | Размер: 5.6 KiB После Ширина: | Высота: | Размер: 729 B |
До Ширина: | Высота: | Размер: 6.6 KiB После Ширина: | Высота: | Размер: 729 B |
До Ширина: | Высота: | Размер: 5.8 KiB После Ширина: | Высота: | Размер: 978 B |
До Ширина: | Высота: | Размер: 5.8 KiB После Ширина: | Высота: | Размер: 978 B |
До Ширина: | Высота: | Размер: 5.8 KiB После Ширина: | Высота: | Размер: 528 B |
До Ширина: | Высота: | Размер: 6.8 KiB После Ширина: | Высота: | Размер: 528 B |
|
@ -1 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><style>.cls-1{fill:none;}.cls-2{fill:#fff;}.cls-3{fill:#e1e1e5;}.cls-4{fill:#767aa8;}.cls-5{fill:#f9f9fa;}.cls-6{fill:#cd6f14;}</style></defs><title>icons</title><path class="cls-1" d="M5.36,20.85H19.86l5.33,5.81a.63.63,0,0,0,.46.17,2.31,2.31,0,0,0,1.47-.76,2.17,2.17,0,0,0,.75-1.57A2.22,2.22,0,0,1,27.12,26c-.69.69-1.56,1-1.93.59L19.86,20.8H5.36A1.32,1.32,0,0,1,4,19.48V14.35H4v5.17A1.32,1.32,0,0,0,5.36,20.85Z"/><path class="cls-1" d="M24.12,20.8l0,0a1.32,1.32,0,0,0,1.27-1.31v0A1.32,1.32,0,0,1,24.12,20.8Z"/><path class="cls-2" d="M23.6,20.32h.51a.84.84,0,0,0,.84-.84V14.31a.84.84,0,0,0-.84-.84H21.33a7.34,7.34,0,0,1-1.45,3.86l.63.63a.82.82,0,0,1,.77.22Z"/><path class="cls-2" d="M19.06,19.41l-.63-.63a7.39,7.39,0,0,1-11.82-5.3H5.36a.84.84,0,0,0-.84.84v5.17a.84.84,0,0,0,.84.84h14l-.13-.14A.82.82,0,0,1,19.06,19.41Z"/><path class="cls-3" d="M5.36,20.8H19.86l-.44-.48h-14a.84.84,0,0,1-.84-.84V14.31a.84.84,0,0,1,.84-.84H6.61c0-.16,0-.31,0-.47,0,0,0,0,0,0H5.36A1.32,1.32,0,0,0,4,14.35v5.13A1.32,1.32,0,0,0,5.36,20.8Z"/><path class="cls-3" d="M24.1,13.48a.84.84,0,0,1,.84.84v5.17a.84.84,0,0,1-.84.84H23.6l.26.24.26.24a1.32,1.32,0,0,0,1.3-1.32V14.36A1.32,1.32,0,0,0,24.1,13H21.34v0c0,.15,0,.31,0,.46Z"/><path class="cls-4" d="M8.75,18.11a7.4,7.4,0,0,0,9.68.67l.63.63A2.22,2.22,0,0,1,20.51,18l-.63-.63a7.34,7.34,0,0,0,1.45-3.86c0-.15,0-.31,0-.46a7.37,7.37,0,0,0-1.59-4.71l-.1-.12c-.14-.17-.29-.34-.45-.5A7.39,7.39,0,0,0,6.59,13c0,.16,0,.31,0,.47A7.36,7.36,0,0,0,8.75,18.11ZM8.28,10.9a6,6,0,0,1,.43-1h0a6,6,0,0,1,10.46,0h0c0,.07.06.15.1.22s.08.13.11.2l-.06-.08a6.15,6.15,0,0,1,.28.63A6,6,0,0,1,8.87,16.08l0,.08c-.06-.09-.1-.19-.15-.28l-.14-.26c-.05-.11-.11-.21-.15-.32a6,6,0,0,1-.25-.66v0A6,6,0,0,1,8,13.83v-.05a5.79,5.79,0,0,1,.27-2.87Z"/><path class="cls-5" d="M14.36,7.56A6,6,0,0,0,9.58,9.93h9.56A6,6,0,0,0,14.36,7.56Z"/><path class="cls-2" d="M8,12.92a6,6,0,0,1,.35-2h0A5.79,5.79,0,0,0,8,13.77,6.05,6.05,0,0,1,8,12.92Z"/><path class="cls-2" d="M8.33,13.59a6,6,0,0,0,.54,2.49A6,6,0,0,0,19.66,10.9H9A6,6,0,0,0,8.33,13.59Z"/><path class="cls-3" d="M8,12.92a6.05,6.05,0,0,0,.06.86v.05a6,6,0,0,0,.17.78v0a6,6,0,0,0,.25.66c0,.11.1.21.15.32l.14.26c.05.09.1.19.15.28l0-.08A6,6,0,0,1,9,10.9H19.66a6.15,6.15,0,0,0-.28-.63l.06.08c0-.07-.07-.13-.11-.2s-.06-.15-.1-.22h0a6,6,0,0,0-10.46,0h0a6,6,0,0,0-.43,1h0A6,6,0,0,0,8,12.92Zm6.41-5.35a6,6,0,0,1,4.78,2.37H9.58A6,6,0,0,1,14.36,7.56Z"/><path class="cls-6" d="M21.1,22.15,23.25,20l.61.56-.26-.24-2.32-2.13a.82.82,0,0,0-.77-.22,2.22,2.22,0,0,0-1.44,1.44.82.82,0,0,0,.22.77l.13.14.44.48,5.33,5.81c.37.37,1.24.1,1.93-.59a2.22,2.22,0,0,0,.75-1.53.59.59,0,0,0-.16-.36L26.4,22.93,24,25.32Z"/><path class="cls-4" d="M23.86,20.56,23.25,20,21.1,22.15,24,25.32l2.39-2.39-2.28-2.09h0l0,0Z"/><path class="cls-2" d="M5.36,21.85H19.42l5,5.49a1.65,1.65,0,0,0,1.2.49,3.27,3.27,0,0,0,2.18-1c1.12-1.12,1.37-2.56.59-3.34l-2.58-2.37a2.31,2.31,0,0,0,.59-1.54V14.36A2.32,2.32,0,0,0,24.1,12H22.3A8.37,8.37,0,0,0,8,7,8.31,8.31,0,0,0,5.63,12H5.36A2.32,2.32,0,0,0,3,14.36v5.17A2.32,2.32,0,0,0,5.36,21.85ZM4,14.36H4A1.32,1.32,0,0,1,5.36,13H6.59s0,0,0,0A7.39,7.39,0,0,1,19.2,7.69c.16.16.31.33.45.5l.1.12A7.37,7.37,0,0,1,21.34,13v0H24.1a1.32,1.32,0,0,1,1.32,1.32v5.17a1.32,1.32,0,0,1-1.27,1.31h0l2.28,2.09,1.31,1.21a.59.59,0,0,1,.16.36,2.17,2.17,0,0,1-.75,1.57,2.31,2.31,0,0,1-1.47.76.63.63,0,0,1-.46-.17l-5.33-5.81H5.36A1.32,1.32,0,0,1,4,19.52Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="8 8 16 16 "><title>Icons / Search</title><g fill="none"><path d="M0 0h32v32H0z"/><path d="M23.7 22.3l-4.8-4.8c1.8-2.5 1.4-6.1-1-8.1s-5.9-1.9-8.1.4c-2.3 2.2-2.4 5.7-.4 8.1 2 2.4 5.6 2.8 8.1 1l4.8 4.8c.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4zM14 18c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4c0 1.1-.4 2.1-1.1 2.9-.8.7-1.8 1.1-2.9 1.1z" fill="#0A84FF"/></g></svg>
|
До Ширина: | Высота: | Размер: 3.4 KiB После Ширина: | Высота: | Размер: 417 B |
|
@ -1 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><style>.cls-1{fill:none;}.cls-2{fill:#fff;}.cls-3{fill:#d9ebff;}.cls-4{fill:#f9f9fa;}.cls-5{fill:#e1e1e6;}.cls-6{fill:#59acff;}</style></defs><title>icons</title><path class="cls-1" d="M5.36,20.8A1.32,1.32,0,0,1,4,19.48v0a1.32,1.32,0,0,0,1.32,1.32H19.86l1.2,1.31,0,0L19.86,20.8Z"/><path class="cls-1" d="M24.35,20.75l0,0a1.3,1.3,0,0,0,1-1.26v0A1.3,1.3,0,0,1,24.35,20.75Z"/><path class="cls-1" d="M25.19,26.61,24,25.32l0,0,1.2,1.31a.63.63,0,0,0,.46.17,2.31,2.31,0,0,0,1.47-.76,2.17,2.17,0,0,0,.75-1.57A2.22,2.22,0,0,1,27.12,26C26.43,26.72,25.56,27,25.19,26.61Z"/><path class="cls-2" d="M4.53,14.31v5.17a.84.84,0,0,0,.84.84h14l-.13-.14a.82.82,0,0,1-.22-.77l-.63-.63a7.38,7.38,0,0,1-8.11.49.24.24,0,0,1,0,.15.25.25,0,0,1-.22.13.26.26,0,0,1-.12,0,7.75,7.75,0,0,1-3.78-6H5.36A.84.84,0,0,0,4.53,14.31Z"/><path class="cls-2" d="M20.34,17.8l0,0c.05,0,.53-.37,1.33.48.29.31,1.24,1.19,2.2,2.07h.23a.84.84,0,0,0,.84-.84V14.31a.84.84,0,0,0-.84-.84H21.8A6.19,6.19,0,0,1,21,16.2l0,.07a.24.24,0,0,1-.23.16h-.08a.23.23,0,0,1-.11-.1,7.32,7.32,0,0,1-.64,1Z"/><path class="cls-3" d="M19.87,17.33a7.32,7.32,0,0,0,.64-1,.25.25,0,0,1,0-.22.88.88,0,0,1,.08-.15,5.77,5.77,0,0,0,.78-3.17,7.35,7.35,0,0,0-1.58-4.45l-.1-.12c-.14-.17-.29-.34-.45-.5a7.39,7.39,0,0,0-12.59,4.6,7.58,7.58,0,0,0,3.6,6.78.24.24,0,0,1,.11.2,7.38,7.38,0,0,0,8.11-.49l.63.63a.82.82,0,0,0,.22.77l.13.14h-14a.84.84,0,0,1-.84-.84V14.31a.84.84,0,0,1,.84-.84h.81c0-.16,0-.3,0-.44H5.36A1.32,1.32,0,0,0,4,14.36v5.13A1.32,1.32,0,0,0,5.36,20.8H19.86l1.22,1.33,2-1.92c-.77-.72-1.46-1.36-1.71-1.63s-.62-.44-.68-.41a.24.24,0,0,1-.34,0s0-.06,0-.09a.25.25,0,0,1,.06-.24ZM14,18.91a6,6,0,0,1-5.1-2.82l0,.08c-.06-.09-.1-.19-.15-.28l-.14-.26c-.05-.11-.11-.21-.15-.32a6,6,0,0,1-.25-.66v0A6,6,0,0,1,8,13.83v-.05a6.06,6.06,0,0,1,.7-3.84h0a6,6,0,0,1,10.46,0l.12.22c0,.06.08.13.11.2l-.06-.08-.24-.33H9.58a6,6,0,0,0-.61,1H19.66a6,6,0,0,1-5.69,8Z"/><path class="cls-3" d="M24.94,14.31v5.17a.84.84,0,0,1-.84.84h-.23l.47.43a1.3,1.3,0,0,0,1.07-1.27V14.36A1.32,1.32,0,0,0,24.1,13H21.82c0,.15,0,.3,0,.44H24.1A.84.84,0,0,1,24.94,14.31Z"/><path class="cls-4" d="M14.36,7.56A6,6,0,0,0,9.58,9.93h9.56A6,6,0,0,0,14.36,7.56Z"/><path class="cls-2" d="M19.66,10.9H9a6,6,0,0,0-.1,5.18A6,6,0,0,0,19.66,10.9Z"/><path class="cls-2" d="M8.31,10.9h0A5.79,5.79,0,0,0,8,13.77a5.93,5.93,0,0,1,.29-2.87Z"/><path class="cls-5" d="M8.75,9.93h0a6,6,0,0,0-.43,1h0A6,6,0,0,1,8.75,9.93Z"/><path class="cls-6" d="M9,10.9a6,6,0,0,1,10.17-1l.24.33.06.08c0-.07-.07-.13-.11-.2l-.12-.22A6,6,0,0,0,8,13.77v.05a6,6,0,0,0,.17.78v0a6,6,0,0,0,.25.66c0,.11.1.21.15.32l.14.26c.05.09.1.19.15.28l0-.08A6,6,0,0,1,9,10.9Z"/><path class="cls-3" d="M26.4,22.93,24,25.32l1.18,1.29c.37.37,1.24.1,1.93-.59a2.22,2.22,0,0,0,.75-1.53.59.59,0,0,0-.16-.36Z"/><path class="cls-6" d="M28.42,23.43l-2.58-2.37a2.31,2.31,0,0,0,.59-1.54V14.36A2.32,2.32,0,0,0,24.1,12H22.3A8.37,8.37,0,0,0,8,7,8.31,8.31,0,0,0,5.63,12H5.36A2.32,2.32,0,0,0,3,14.36v5.17a2.32,2.32,0,0,0,2.32,2.32H19.42l5,5.49a1.65,1.65,0,0,0,1.2.49,3.27,3.27,0,0,0,2.18-1C29,25.65,29.2,24.22,28.42,23.43ZM20.28,18s0,.06,0,.09a.24.24,0,0,0,.34,0c.06,0,.29,0,.68.41s.94.91,1.71,1.63l-2,1.92,0,0-1.2-1.31H5.36A1.32,1.32,0,0,1,4,19.52V14.36A1.32,1.32,0,0,1,5.36,13h.77c0,.14,0,.28,0,.44a7.75,7.75,0,0,0,3.78,6,.26.26,0,0,0,.12,0,.25.25,0,0,0,.22-.12.24.24,0,0,0,0-.15.24.24,0,0,0-.11-.2,7.58,7.58,0,0,1-3.6-6.78A7.39,7.39,0,0,1,19.2,7.69c.16.16.31.33.45.5l.1.12a7.35,7.35,0,0,1,1.58,4.45,5.77,5.77,0,0,1-.78,3.17.88.88,0,0,0-.08.15.25.25,0,0,0,0,.22.23.23,0,0,0,.11.1h.08a.24.24,0,0,0,.23-.16l0-.07a6.19,6.19,0,0,0,.82-2.72c0-.14,0-.29,0-.44H24.1a1.32,1.32,0,0,1,1.32,1.32v5.17a1.3,1.3,0,0,1-1,1.26l0,0-.47-.43c-1-.88-1.9-1.76-2.2-2.07-.8-.85-1.28-.52-1.33-.48l0,0A.25.25,0,0,0,20.28,18Zm6.84,8a2.31,2.31,0,0,1-1.47.76.63.63,0,0,1-.46-.17L24,25.34l0,0,2.39-2.39,1.31,1.21a.59.59,0,0,1,.16.36A2.17,2.17,0,0,1,27.12,26.07Z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="8 8 16 16 "><title>Icons / Search</title><g fill="none"><path d="M0 0h32v32H0z"/><path d="M23.7 22.3l-4.8-4.8c1.8-2.5 1.4-6.1-1-8.1s-5.9-1.9-8.1.4c-2.3 2.2-2.4 5.7-.4 8.1 2 2.4 5.6 2.8 8.1 1l4.8 4.8c.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4zM14 18c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4c0 1.1-.4 2.1-1.1 2.9-.8.7-1.8 1.1-2.9 1.1z" fill="#3E3D40"/></g></svg>
|
До Ширина: | Высота: | Размер: 3.9 KiB После Ширина: | Высота: | Размер: 417 B |
|
@ -116,22 +116,20 @@
|
|||
|
||||
#onboarding-tour-list > li {
|
||||
list-style: none;
|
||||
border-inline-start: 6px solid transparent;
|
||||
border-radius: 2px;
|
||||
padding-inline-start: 49px;
|
||||
padding-top: 14px;
|
||||
padding-bottom: 14px;
|
||||
margin-inline-start: 10px;
|
||||
margin-inline-start: 16px;
|
||||
margin-bottom: 9px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left 10px top 7px;
|
||||
background-size: 34px;
|
||||
background-position: left 17px top 14px;
|
||||
background-size: 20px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#onboarding-tour-list > li:dir(rtl) {
|
||||
background-position-x: right 10px;
|
||||
background-position-x: right 17px;
|
||||
}
|
||||
|
||||
#onboarding-tour-list > li.onboarding-complete::before {
|
||||
|
@ -147,8 +145,7 @@
|
|||
|
||||
#onboarding-tour-list > li.onboarding-active,
|
||||
#onboarding-tour-list > li:hover {
|
||||
border-inline-start-color: #5ce6e6;
|
||||
background-color: #fff;
|
||||
color: #0A84FF;
|
||||
}
|
||||
|
||||
/* Sync tour */
|
||||
|
@ -221,15 +218,19 @@
|
|||
.onboarding-tour-content {
|
||||
grid-row: tour-page-start / tour-button-start;
|
||||
grid-column: tour-content-start / tour-page-end;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-inline-start: 0;
|
||||
padding-inline-end: 27px;
|
||||
padding: 0;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.onboarding-tour-content > img {
|
||||
width: 352px;
|
||||
margin: 0 calc(50% - 176px);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* These illustrations need to be stuck on the right side to the border. Thus we
|
||||
need to flip them horizontally on RTL . */
|
||||
.onboarding-tour-content > img:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.onboarding-tour-content > iframe {
|
||||
|
@ -365,6 +366,10 @@
|
|||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
#onboarding-notification-icon:dir(rtl) {
|
||||
background-position: right 34px center;
|
||||
}
|
||||
|
||||
#onboarding-notification-icon::after {
|
||||
--height: 22px;
|
||||
content: attr(data-tooltip);
|
||||
|
@ -396,8 +401,8 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
offset-block-start: 50%;
|
||||
offset-inline-start: 50%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ var onboardingTours = [
|
|||
let div = win.document.createElement("div");
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-private-browsing.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-private-browsing.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-private-browsing.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-private-browsing.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<img src="resource://onboarding/img/figure_private.svg" />
|
||||
|
@ -82,8 +82,8 @@ var onboardingTours = [
|
|||
let div = win.document.createElement("div");
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-addons.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-addons.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-addons.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-addons.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<img src="resource://onboarding/img/figure_addons.svg" />
|
||||
|
@ -109,8 +109,8 @@ var onboardingTours = [
|
|||
let div = win.document.createElement("div");
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-customize.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-customize.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-customize.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-customize.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<img src="resource://onboarding/img/figure_customize.svg" />
|
||||
|
@ -124,7 +124,7 @@ var onboardingTours = [
|
|||
},
|
||||
{
|
||||
id: "onboarding-tour-search",
|
||||
tourNameId: "onboarding.tour-search",
|
||||
tourNameId: "onboarding.tour-search2",
|
||||
getNotificationStrings(bundle) {
|
||||
return {
|
||||
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-search.title"),
|
||||
|
@ -136,8 +136,8 @@ var onboardingTours = [
|
|||
let div = win.document.createElement("div");
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-search.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-search.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-search.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-search.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<img src="resource://onboarding/img/figure_search.svg" />
|
||||
|
@ -165,8 +165,8 @@ var onboardingTours = [
|
|||
"onboarding.tour-default-browser.win7.button" : "onboarding.tour-default-browser.button";
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-default-browser.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-default-browser.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-default-browser.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-default-browser.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<img src="resource://onboarding/img/figure_default.svg" />
|
||||
|
@ -180,7 +180,7 @@ var onboardingTours = [
|
|||
},
|
||||
{
|
||||
id: "onboarding-tour-sync",
|
||||
tourNameId: "onboarding.tour-sync",
|
||||
tourNameId: "onboarding.tour-sync2",
|
||||
getNotificationStrings(bundle) {
|
||||
return {
|
||||
title: bundle.GetStringFromName("onboarding.notification.onboarding-tour-sync.title"),
|
||||
|
@ -193,8 +193,8 @@ var onboardingTours = [
|
|||
div.classList.add("onboarding-no-button");
|
||||
div.innerHTML = `
|
||||
<section class="onboarding-tour-description">
|
||||
<h1 data-l10n-id="onboarding.tour-sync.title"></h1>
|
||||
<p data-l10n-id="onboarding.tour-sync.description"></p>
|
||||
<h1 data-l10n-id="onboarding.tour-sync.title2"></h1>
|
||||
<p data-l10n-id="onboarding.tour-sync.description2"></p>
|
||||
</section>
|
||||
<section class="onboarding-tour-content">
|
||||
<form>
|
||||
|
@ -260,7 +260,7 @@ class Onboarding {
|
|||
if (doc.hidden) {
|
||||
// When the preloaded-browser feature is on,
|
||||
// it would preload an hidden about:newtab in the background.
|
||||
// We don't wnat to show notification in that hidden state.
|
||||
// We don't want to show notification in that hidden state.
|
||||
let onVisible = () => {
|
||||
if (!doc.hidden) {
|
||||
doc.removeEventListener("visibilitychange", onVisible);
|
||||
|
@ -324,11 +324,9 @@ class Onboarding {
|
|||
case "onboarding-overlay":
|
||||
this.toggleOverlay();
|
||||
break;
|
||||
|
||||
case "onboarding-notification-close-btn":
|
||||
this.hideNotification();
|
||||
break;
|
||||
|
||||
case "onboarding-notification-action-btn":
|
||||
let tourId = this._notificationBar.dataset.targetTourId;
|
||||
this.toggleOverlay();
|
||||
|
@ -488,7 +486,7 @@ class Onboarding {
|
|||
_renderNotificationBar() {
|
||||
let div = this._window.document.createElement("div");
|
||||
div.id = "onboarding-notification-bar";
|
||||
// Here we use `innerHTML` is for more friendly reading.
|
||||
// We use `innerHTML` for more friendly reading.
|
||||
// The security should be fine because this is not from an external input.
|
||||
div.innerHTML = `
|
||||
<div id="onboarding-notification-icon"></div>
|
||||
|
@ -524,7 +522,7 @@ class Onboarding {
|
|||
_renderOverlay() {
|
||||
let div = this._window.document.createElement("div");
|
||||
div.id = "onboarding-overlay";
|
||||
// Here we use `innerHTML` is for more friendly reading.
|
||||
// We use `innerHTML` for more friendly reading.
|
||||
// The security should be fine because this is not from an external input.
|
||||
div.innerHTML = `
|
||||
<div id="onboarding-overlay-dialog">
|
||||
|
|
|
@ -6,70 +6,69 @@ onboarding.overlay-title=Getting started with %S
|
|||
onboarding.hidden-checkbox-label-text=Mark all as complete, and hide the tour
|
||||
#LOCALIZATION NOTE(onboarding.button.learnMore): this string is used as a button label, displayed near the message, and shared across all the onboarding notifications.
|
||||
onboarding.button.learnMore=Learn More
|
||||
# LOCALIZATION NOTE(onboarding.notification-icon-tool-tip): %S is brandShortName.
|
||||
# LOCALIZATION NOTE(onboarding.notification-icon-tool-tip): This string will be used to show the tooltip alongside the notification icon. %S is brandShortName.
|
||||
onboarding.notification-icon-tool-tip=New to %S?
|
||||
|
||||
onboarding.tour-search=One-Click Search
|
||||
onboarding.tour-search.title=Find the needle or the haystack.
|
||||
# LOCALIZATION NOTE (onboarding.tour-search.description): If Amazon is not part
|
||||
onboarding.tour-search2=Search
|
||||
onboarding.tour-search.title2=Find it faster.
|
||||
# LOCALIZATION NOTE (onboarding.tour-search.description2): If Amazon is not part
|
||||
# of the default searchplugins for your locale, you can replace it with another
|
||||
# ecommerce website (if you're shipping one), but not with a general purpose
|
||||
# search engine (Google, Bing, Yandex, etc.). Alternatively, only reference
|
||||
# Wikipedia and drop Amazon from the text.
|
||||
onboarding.tour-search.description=Having a default search engine doesn’t mean it’s the only one you use. Pick a search engine or a site, like Amazon or Wikipedia, to search on the fly.
|
||||
onboarding.tour-search.description2=Having a default search engine doesn’t mean it’s the only one you can use. Choose a search engine or a site, like Amazon or Wikipedia, right from the search box.
|
||||
onboarding.tour-search.button=Open One-Click Search
|
||||
onboarding.notification.onboarding-tour-search.title=Find it faster.
|
||||
onboarding.notification.onboarding-tour-search.message=Access all of your favorite search engines with a click. Search the whole Web or just one website right from the search box.
|
||||
|
||||
onboarding.tour-private-browsing=Private Browsing
|
||||
onboarding.tour-private-browsing.title=A little privacy goes a long way.
|
||||
# LOCALIZATION NOTE(onboarding.tour-private-browsing.description): %S is brandShortName.
|
||||
onboarding.tour-private-browsing.description=Browse the internet without saving your searches or the sites you visited. When your session ends, the cookies disappear from %S like they were never there.
|
||||
onboarding.tour-private-browsing.title2=Browse by yourself.
|
||||
# LOCALIZATION NOTE(onboarding.tour-private-browsing.description2): %S is brandShortName.
|
||||
onboarding.tour-private-browsing.description2=Want to keep something to yourself? Use Private Browsing with Tracking Protection. When you close your session, %S clears search and browsing history.
|
||||
onboarding.tour-private-browsing.button=Show Private Browsing in Menu
|
||||
onboarding.notification.onboarding-tour-private-browsing.title=Browse by yourself.
|
||||
onboarding.notification.onboarding-tour-private-browsing.message=There’s no reason to share your online life with trackers every time you browse. Want to keep something to yourself? Use Private Browsing with Tracking Protection.
|
||||
|
||||
onboarding.tour-addons=Add-ons
|
||||
onboarding.tour-addons.title=Add more functionality.
|
||||
# LOCALIZATION NOTE(onboarding.tour-addons.description): This string will be used in the add-on tour description. %1$S is brandShortName
|
||||
onboarding.tour-addons.description=Add-ons expand %1$S’s built-in features, so %1$S works the way you do. Compare prices, check the weather or express your personality with a custom theme.
|
||||
onboarding.tour-addons.title2=Get more done.
|
||||
# LOCALIZATION NOTE(onboarding.tour-addons.description2): This string will be used in the add-on tour description. %S is brandShortName
|
||||
onboarding.tour-addons.description2=Add-ons let you add features to %S, so your browser works harder for you. Compare prices, check the weather or express your personality with a custom theme.
|
||||
onboarding.tour-addons.button=Show Add-ons in Menu
|
||||
onboarding.notification.onboarding-tour-addons.title=Get more done.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-addons.message): %S is brandShortName.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-addons.message): This string will be used in the notification message for the add-ons tour. %S is brandShortName.
|
||||
onboarding.notification.onboarding-tour-addons.message=Add-ons are small apps you can add to %S that do lots of things — from managing to-do lists, to downloading videos, to changing the look of your browser.
|
||||
|
||||
onboarding.tour-customize=Customize
|
||||
onboarding.tour-customize.title=Do things your way.
|
||||
# LOCALIZATION NOTE(onboarding.tour-customize.description): This string will be used in the customize tour description. %S is brandShortName
|
||||
onboarding.tour-customize.description=Drag, drop, and reorder %S’s toolbar and menu to fit your needs. You can even select a compact theme to give websites more room.
|
||||
onboarding.tour-customize.title2=Rearrange your toolbar.
|
||||
# LOCALIZATION NOTE(onboarding.tour-customize.description2): This string will be used in the customize tour description. %S is brandShortName
|
||||
onboarding.tour-customize.description2=Put the tools you use most right at your fingertips. Drag, drop, and reorder %S’s toolbar and menu to fit your needs. Or choose a compact theme to make more room for tabbed browsing.
|
||||
onboarding.tour-customize.button=Show Customize in Menu
|
||||
onboarding.notification.onboarding-tour-customize.title=Rearrange your toolbar.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-customize.message): %S is brandShortName.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-customize.message): This string will be used in the notification message for Customize tour. %S is brandShortName.
|
||||
onboarding.notification.onboarding-tour-customize.message=Put the tools you use most right at your fingertips. Add more options to your toolbar. Or select a theme to make %S reflect your personality.
|
||||
|
||||
onboarding.tour-default-browser=Default Browser
|
||||
onboarding.tour-default-browser.title=We’re there for you.
|
||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.description): This string will be used in the default browser tour description. %1$S is brandShortName
|
||||
onboarding.tour-default-browser.description=Love %1$S? Set it as your default browser. Then when you open a link from another application, %1$S has you covered.
|
||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.title2): This string will be used in the default browser tour title. %S is brandShortName
|
||||
onboarding.tour-default-browser.title2=Make %S your go-to browser.
|
||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.description2): This string will be used in the default browser tour description. %1$S is brandShortName
|
||||
onboarding.tour-default-browser.description2=Love %1$S? Set it as your default browser. Open a link from another application, and %1$S will be there for you.
|
||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.button): Label for a button to open the OS default browser settings where it's not possible to set the default browser directly. (OSX, Linux, Windows 8 and higher)
|
||||
onboarding.tour-default-browser.button=Open Default Browser Settings
|
||||
# LOCALIZATION NOTE(onboarding.tour-default-browser.win7.button): Label for a button to directly set the default browser (Windows 7). %S is brandShortName
|
||||
onboarding.tour-default-browser.win7.button=Make %S Your Default Browser
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-default-browser.title): %S is brandShortName.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-default-browser.title): This string will be used in the notification message for the default browser tour. %S is brandShortName.
|
||||
onboarding.notification.onboarding-tour-default-browser.title=Make %S your go-to browser.
|
||||
# LOCALIZATION NOTE(onboarding.notification.onboarding-tour-default-browser.message): %1$S is brandShortName
|
||||
onboarding.notification.onboarding-tour-default-browser.message=It doesn’t take much to get the most from %1$S. Just set %1$S as your default browser and put control, customization, and protection on autopilot.
|
||||
|
||||
onboarding.tour-sync=Firefox Sync
|
||||
onboarding.tour-sync.title=Sync brings it all together.
|
||||
onboarding.tour-sync.description=Access your bookmarks and passwords on any device. You can even send a tab from your laptop to your phone! Better yet, you can choose what you sync and what you don’t.
|
||||
|
||||
onboarding.tour-sync2=Sync
|
||||
onboarding.tour-sync.title2=Pick up where you left off.
|
||||
onboarding.tour-sync.description2=Sync makes it easy to access bookmarks, passwords, and even open tabs on all your devices. Sync also gives you control of the types of information you want, and don’t want, to share.
|
||||
# LOCALIZATION NOTE(onboarding.tour-sync.form.title): This string is displayed
|
||||
# as a title and followed by onboarding.tour-sync.form.description.
|
||||
# Your translation should be consistent with the form displayed in
|
||||
# about:accounts when signing up to Firefox Account.
|
||||
onboarding.tour-sync.form.title=Create a Firefox Account
|
||||
|
||||
# LOCALIZATION NOTE(onboarding.tour-sync.form.description): The description
|
||||
# continues after onboarding.tour-sync.form.title to create a complete sentence.
|
||||
# If it's not possible for your locale, you can translate this string as
|
||||
|
|
|
@ -81,9 +81,7 @@ function shutdown(data, reason) { // eslint-disable-line no-unused-vars
|
|||
id: ADDON_ID,
|
||||
resourceURI: addonResourceURI
|
||||
});
|
||||
if (webExtension.started) {
|
||||
stop(webExtension, reason);
|
||||
}
|
||||
stop(webExtension, reason);
|
||||
}
|
||||
|
||||
function install(data, reason) {} // eslint-disable-line no-unused-vars
|
||||
|
|
|
@ -107,11 +107,6 @@
|
|||
; Register AccessibleHandler.dll with COM (this writes to HKLM)
|
||||
${RegisterAccessibleHandler}
|
||||
|
||||
!ifndef HAVE_64BIT_BUILD
|
||||
; Clean up any IAccessible registry corruption
|
||||
${FixCorruptOleAccRegistration}
|
||||
!endif
|
||||
|
||||
!ifdef MOZ_MAINTENANCE_SERVICE
|
||||
Call IsUserAdmin
|
||||
Pop $R0
|
||||
|
@ -927,49 +922,6 @@
|
|||
!macroend
|
||||
!define RegisterAccessibleHandler "!insertmacro RegisterAccessibleHandler"
|
||||
|
||||
!ifndef HAVE_64BIT_BUILD
|
||||
!define IID_IAccessible "{618736E0-3C3D-11CF-810C-00AA00389B71}"
|
||||
!define CLSID_UniversalMarshaler "{00020404-0000-0000-C000-000000000046}"
|
||||
!define OleAccTypeLib "{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}"
|
||||
!define OleAccTypeLibVersion "1.1"
|
||||
Function FixCorruptOleAccRegistration
|
||||
Push $0
|
||||
|
||||
; Read IAccessible's ProxyStubClsid32. If it is not CLSID_UniversalMarshaler
|
||||
; then we must be running Windows 10 Creators Update which does not use a
|
||||
; type library.
|
||||
ReadRegStr $0 HKCR "Interface\${IID_IAccessible}\ProxyStubClsid32" ""
|
||||
${Unless} "$0" == "${CLSID_UniversalMarshaler}"
|
||||
Pop $0
|
||||
Return
|
||||
${EndIf}
|
||||
|
||||
Push $1
|
||||
|
||||
; IAccessible is using the universal marshler, therefore we expect a valid
|
||||
; TypeLib key to exist
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCR "Interface\${IID_IAccessible}\TypeLib" ""
|
||||
ReadRegStr $1 HKCR "Interface\${IID_IAccessible}\TypeLib" "Version"
|
||||
ReadRegStr $0 HKCR "TypeLib\$0\$1\0\win32" ""
|
||||
Pop $1
|
||||
${IfNot} ${Errors}
|
||||
${AndIf} ${FileExists} "$0"
|
||||
Pop $0
|
||||
Return
|
||||
${EndIf}
|
||||
|
||||
Pop $0
|
||||
|
||||
; Some third-party code has previously overridden system typelibs
|
||||
; with their own but did not clean itself up during uninstall.
|
||||
; Revert to the system typelib.
|
||||
WriteRegStr HKCR "Interface\${IID_IAccessible}\TypeLib" "" "${OleAccTypeLib}"
|
||||
WriteRegStr HKCR "Interface\${IID_IAccessible}\TypeLib" "Version" "${OleAccTypeLibVersion}"
|
||||
FunctionEnd
|
||||
!define FixCorruptOleAccRegistration "Call FixCorruptOleAccRegistration"
|
||||
!endif
|
||||
|
||||
; Removes various registry entries for reasons noted below (does not use SHCTX).
|
||||
!macro RemoveDeprecatedKeys
|
||||
StrCpy $0 "SOFTWARE\Classes"
|
||||
|
|
|
@ -856,6 +856,17 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
|||
<!ENTITY customizeMode.lwthemes.menuGetMore "Get More Themes">
|
||||
<!ENTITY customizeMode.lwthemes.menuGetMore.accessKey "G">
|
||||
<!ENTITY customizeMode.emptyOverflowList.description "Drag and drop items here to keep them within reach but out of your toolbar…">
|
||||
<!ENTITY customizeMode.uidensity "Density">
|
||||
<!ENTITY customizeMode.uidensity.menuNormal.label "Normal">
|
||||
<!ENTITY customizeMode.uidensity.menuNormal.tooltip "Normal">
|
||||
<!ENTITY customizeMode.uidensity.menuNormal.accessKey "N">
|
||||
<!ENTITY customizeMode.uidensity.menuCompact.label "Compact">
|
||||
<!ENTITY customizeMode.uidensity.menuCompact.tooltip "Compact">
|
||||
<!ENTITY customizeMode.uidensity.menuCompact.accessKey "C">
|
||||
<!ENTITY customizeMode.uidensity.menuTouch.label "Touch">
|
||||
<!ENTITY customizeMode.uidensity.menuTouch.tooltip "Touch">
|
||||
<!ENTITY customizeMode.uidensity.menuTouch.accessKey "T">
|
||||
<!ENTITY customizeMode.uidensity.autoTouchMode.checkbox.label "Use Touch for Tablet Mode">
|
||||
|
||||
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">
|
||||
<!ENTITY getUserMedia.selectCamera.accesskey "C">
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# 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/.
|
||||
|
||||
uiDensity.menu-button-touch.acceltext=Tablet Mode Enabled
|
|
@ -25,6 +25,9 @@
|
|||
locale/browser/browser.properties (%chrome/browser/browser.properties)
|
||||
locale/browser/customizableui/customizableWidgets.properties (%chrome/browser/customizableui/customizableWidgets.properties)
|
||||
locale/browser/lightweightThemes.properties (%chrome/browser/lightweightThemes.properties)
|
||||
#ifdef XP_WIN
|
||||
locale/browser/uiDensity.properties (%chrome/browser/uiDensity.properties)
|
||||
#endif
|
||||
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
|
||||
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
|
||||
locale/browser/pageInfo.dtd (%chrome/browser/pageInfo.dtd)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
}
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
|
||||
|
||||
/* Go button */
|
||||
|
|
|
@ -245,19 +245,28 @@
|
|||
height: 16px;
|
||||
}
|
||||
|
||||
#customization-uidensity-button > .box-inherit > .box-inherit > .button-text,
|
||||
#customization-lwtheme-button > .box-inherit > .box-inherit > .button-text {
|
||||
/* Sadly, button.css thinks its margins are perfect for everyone. */
|
||||
margin-inline-start: 6px !important;
|
||||
}
|
||||
|
||||
#customization-uidensity-button > .box-inherit > .box-inherit > .button-icon,
|
||||
#customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 2px;
|
||||
background-image: url("chrome://browser/content/default-theme-icon.svg");
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
#customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
|
||||
background-image: url("chrome://browser/content/default-theme-icon.svg");
|
||||
}
|
||||
|
||||
#customization-uidensity-button > .box-inherit > .box-inherit > .button-icon {
|
||||
background-image: url("chrome://browser/skin/customizableui/density-normal.svg");
|
||||
}
|
||||
|
||||
%ifndef MOZ_PHOTON_THEME
|
||||
#main-window[customize-entered] #customization-panel-container {
|
||||
background-image: url("chrome://browser/skin/customizableui/customizeMode-separatorHorizontal.png"),
|
||||
|
@ -407,18 +416,38 @@ toolbarpaletteitem[place="toolbar"]:not([mousedown="true"]):-moz-focusring {
|
|||
margin-right: 0;
|
||||
}
|
||||
|
||||
#customization-uidensity-touch-spacer {
|
||||
border-top: 1px solid ThreeDLightShadow;
|
||||
margin: 0 -10px 10px;
|
||||
}
|
||||
|
||||
#customization-uidensity-autotouchmode-checkbox {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#customization-uidensity-menu > .panel-arrowcontainer > .panel-arrowcontent,
|
||||
#customization-lwtheme-menu > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
#customization-lwtheme-menu > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
/* Make the panel padding uniform across all platforms due to the
|
||||
styling of the section headers and footer. */
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#customization-uidensity-menu > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.customization-uidensity-menu-button > .menu-iconic-left > .menu-iconic-icon,
|
||||
.customization-lwtheme-menu-theme > .toolbarbutton-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.customization-uidensity-menu-button,
|
||||
.customization-lwtheme-menu-theme {
|
||||
-moz-appearance: none;
|
||||
border: 1px solid transparent;
|
||||
|
@ -433,21 +462,34 @@ toolbarpaletteitem[place="toolbar"]:not([mousedown="true"]):-moz-focusring {
|
|||
list-style-image: url(chrome://browser/content/default-theme-icon.svg);
|
||||
}
|
||||
|
||||
#customization-uidensity-menu-button-normal {
|
||||
list-style-image: url("chrome://browser/skin/customizableui/density-normal.svg");
|
||||
}
|
||||
|
||||
#customization-uidensity-menu-button-compact {
|
||||
list-style-image: url("chrome://browser/skin/customizableui/density-compact.svg");
|
||||
}
|
||||
|
||||
#customization-uidensity-menu-button-touch {
|
||||
list-style-image: url("chrome://browser/skin/customizableui/density-touch.svg");
|
||||
}
|
||||
|
||||
.customization-uidensity-menu-button[active="true"],
|
||||
.customization-uidensity-menu-button:hover,
|
||||
.customization-lwtheme-menu-theme[active="true"],
|
||||
.customization-lwtheme-menu-theme:hover {
|
||||
background-color: var(--arrowpanel-dimmed);
|
||||
border-color: var(--panel-separator-color);
|
||||
}
|
||||
|
||||
.customization-uidensity-menu-button[active="true"],
|
||||
.customization-uidensity-menu-button:hover:active,
|
||||
.customization-lwtheme-menu-theme[active="true"],
|
||||
.customization-lwtheme-menu-theme:hover:active {
|
||||
background-color: var(--arrowpanel-dimmed-further);
|
||||
}
|
||||
|
||||
.customization-lwtheme-menu-theme > .toolbarbutton-icon {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.customization-uidensity-menu-button > .menu-iconic-text,
|
||||
.customization-lwtheme-menu-theme > .toolbarbutton-text {
|
||||
text-align: start;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!-- 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="32" height="32" viewBox="0 0 32 32">
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="#fff"/>
|
||||
<path d="M3 1h26c1.1 0 2 .479 2 1.071V14H1V2.071C1 1.479 1.9 1 3 1z" fill="#f9f9fa"/>
|
||||
<path d="M1 13.5h30" fill="none" stroke="#adadb3"/>
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="none" stroke="#adadb3" stroke-width="2"/>
|
||||
<g opacity=".8" fill="none" stroke="#0c0c0d" stroke-linecap="round">
|
||||
<path d="M3.5 7.5h6"/>
|
||||
<path stroke-linejoin="round" d="M6.5 4.5l-3 3 3 3"/>
|
||||
</g>
|
||||
<g opacity=".8" fill="none" stroke="#0c0c0d" stroke-linecap="round">
|
||||
<path d="M18.5 7.5h-6"/>
|
||||
<path stroke-linejoin="round" d="M15.5 4.5l3 3-3 3"/>
|
||||
</g>
|
||||
<g opacity=".8" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M28.5 4.5v2h-2"/>
|
||||
<path d="M27.623 9.614a3.03 3.03 0 1 1 .636-3.324"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -0,0 +1,18 @@
|
|||
<!-- 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="32" height="32" viewBox="0 0 32 32">
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="#fff"/>
|
||||
<path d="M3 1h26c1.1 0 2 .627 2 1.4V18H1V2.4C1 1.627 1.9 1 3 1z" fill="#f9f9fa"/>
|
||||
<g opacity=".8" fill="none" stroke="#0c0c0d" stroke-linecap="round">
|
||||
<path d="M25.5 9.5h-6"/>
|
||||
<path stroke-linejoin="round" d="M22.5 6.5l3 3-3 3"/>
|
||||
</g>
|
||||
<path d="M2 17.5h29" fill="none" stroke="#adadb3"/>
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="none" stroke="#adadb3" stroke-width="2"/>
|
||||
<circle cx="9.5" cy="9.5" r="6" fill="#fff" stroke="#adadb3"/>
|
||||
<g opacity=".8" fill="none" stroke="#0c0c0d" stroke-linecap="round">
|
||||
<path d="M6.5 9.5h6"/>
|
||||
<path stroke-linejoin="round" d="M9.5 6.5l-3 3 3 3"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1010 B |
|
@ -0,0 +1,14 @@
|
|||
<!-- 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="32" height="32" viewBox="0 0 32 32">
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="#fff"/>
|
||||
<path d="M2.942 1.073l26-.145a1.88 1.88 0 0 1 2.01 1.718l.108 19.27-30 .168L.951 2.813a1.88 1.88 0 0 1 1.991-1.74z" fill="#f9f9fa"/>
|
||||
<path d="M1 21.5h30" fill="none" stroke="#adadb3"/>
|
||||
<rect x="1" y="1" width="30" height="30" rx="2" ry="2" fill="none" stroke="#adadb3" stroke-width="2"/>
|
||||
<circle cx="15.5" cy="11.5" r="8" fill="#fff" stroke="#adadb3"/>
|
||||
<g opacity=".8" fill="none" stroke="#0c0c0d" stroke-linecap="round">
|
||||
<path d="M12.5 11.5h6"/>
|
||||
<path stroke-linejoin="round" d="M15.5 8.5l-3 3 3 3"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 901 B |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="context-fill" d="M14.5,15h-13C0.7,15,0,14.3,0,13.5v-11C0,1.7,0.7,1,1.5,1h13C15.3,1,16,1.7,16,2.5v11C16,14.3,15.3,15,14.5,15z M2,6v6
|
||||
c0,0.5,0.4,1,0.9,1c0,0,0.1,0,0.1,0h7V5H3C2.5,5,2,5.4,2,5.9C2,5.9,2,6,2,6z M8.5,2C8.2,2,8,2.2,8,2.4c0,0,0,0,0,0.1
|
||||
C8,2.8,8.2,3,8.5,3S9,2.8,9,2.5C9,2.2,8.8,2,8.5,2C8.5,2,8.5,2,8.5,2z M10.4,2c-0.3,0-0.5,0.2-0.5,0.4c0,0,0,0,0,0.1
|
||||
c0,0.3,0.2,0.5,0.5,0.5c0.3,0,0.5-0.2,0.5-0.4c0,0,0,0,0-0.1C10.9,2.2,10.7,2,10.4,2C10.4,2,10.4,2,10.4,2z M13.5,2h-1
|
||||
C12.2,2,12,2.2,12,2.4c0,0,0,0,0,0.1C12,2.8,12.2,3,12.4,3c0,0,0,0,0.1,0h1C13.8,3,14,2.8,14,2.6c0,0,0,0,0-0.1
|
||||
C14,2.2,13.8,2,13.5,2C13.5,2,13.5,2,13.5,2z M14,6c0-0.5-0.4-1-0.9-1c0,0-0.1,0-0.1,0h-1v8h1c0.5,0,1-0.4,1-0.9c0,0,0-0.1,0-0.1V6z
|
||||
"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.0 KiB |
|
@ -1,6 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="context-fill" d="M14.5 15h-13A1.538 1.538 0 0 1 0 13.5v-11A1.538 1.538 0 0 1 1.5 1h13A1.538 1.538 0 0 1 16 2.5v11a1.538 1.538 0 0 1-1.5 1.5zM2 6v6a.945.945 0 0 0 1 1h7V5H3a.945.945 0 0 0-1 1zm6.5-4a.472.472 0 0 0-.5.5.5.5 0 0 0 1 0 .472.472 0 0 0-.5-.5zm1.9 0a.472.472 0 0 0-.5.5.536.536 0 0 0 .5.5.472.472 0 0 0 .5-.5.472.472 0 0 0-.5-.5zm3.1 0h-1a.472.472 0 0 0-.5.5.472.472 0 0 0 .5.5h1a.472.472 0 0 0 .5-.5.472.472 0 0 0-.5-.5zm.5 4a.945.945 0 0 0-1-1h-1v8h1a.945.945 0 0 0 1-1z"/>
|
||||
<path fill="context-fill" d="M14.5,15h-13C0.7,15,0,14.3,0,13.5v-11C0,1.7,0.7,1,1.5,1h13C15.3,1,16,1.7,16,2.5v11C16,14.3,15.3,15,14.5,15z M2,6v6
|
||||
c0,0.5,0.4,1,0.9,1c0,0,0.1,0,0.1,0h1V5H3C2.5,5,2,5.4,2,5.9C2,5.9,2,6,2,6z M8.5,2C8.2,2,8,2.2,8,2.4c0,0,0,0,0,0.1
|
||||
C8,2.8,8.2,3,8.5,3S9,2.8,9,2.5C9,2.2,8.8,2,8.5,2C8.5,2,8.5,2,8.5,2z M10.4,2c-0.3,0-0.5,0.2-0.5,0.4c0,0,0,0,0,0.1
|
||||
c0,0.3,0.2,0.5,0.5,0.5c0.3,0,0.5-0.2,0.5-0.4c0,0,0,0,0-0.1C10.9,2.2,10.7,2,10.4,2C10.4,2,10.4,2,10.4,2z M13.5,2h-1
|
||||
C12.2,2,12,2.2,12,2.4c0,0,0,0,0,0.1C12,2.8,12.2,3,12.4,3c0,0,0,0,0.1,0h1C13.8,3,14,2.8,14,2.6c0,0,0,0,0-0.1
|
||||
C14,2.2,13.8,2,13.5,2C13.5,2,13.5,2,13.5,2z M14,6c0-0.5-0.4-1-0.9-1c0,0-0.1,0-0.1,0H6v8h7c0.5,0,1-0.4,1-0.9c0,0,0-0.1,0-0.1V6z"
|
||||
/>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 803 B После Ширина: | Высота: | Размер: 1.0 KiB |
|
@ -657,14 +657,15 @@ groupbox {
|
|||
|
||||
menulist[indicator=true] > menupopup menuitem:not([image]) > .menu-iconic-left {
|
||||
display: -moz-box;
|
||||
width: 10px;
|
||||
width: 8px;
|
||||
min-width: auto; /* Override the min-width defined in menu.css */
|
||||
height: 10px;
|
||||
margin-inline-end: 6px;
|
||||
}
|
||||
|
||||
menulist[indicator=true] > menupopup menuitem[indicator=true]:not([image]) > .menu-iconic-left {
|
||||
background-image: url(chrome://global/skin/icons/search-arrow-indicator.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 12px 10px;
|
||||
menulist[indicator=true] > menupopup menuitem[indicator=true]:not([image]) > .menu-iconic-left > .menu-iconic-icon {
|
||||
list-style-image: url(chrome://global/skin/icons/search-arrow-indicator.svg);
|
||||
width: 8px;
|
||||
height: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
#ifdef MOZ_PHOTON_THEME
|
||||
skin/classic/browser/customizableui/empty-overflow-panel.png (../shared/customizableui/empty-overflow-panel.png)
|
||||
skin/classic/browser/customizableui/empty-overflow-panel@2x.png (../shared/customizableui/empty-overflow-panel@2x.png)
|
||||
skin/classic/browser/customizableui/density-compact.svg (../shared/customizableui/density-compact.svg)
|
||||
skin/classic/browser/customizableui/density-normal.svg (../shared/customizableui/density-normal.svg)
|
||||
skin/classic/browser/customizableui/density-touch.svg (../shared/customizableui/density-touch.svg)
|
||||
#else
|
||||
skin/classic/browser/customizableui/customize-illustration.png (../shared/customizableui/customize-illustration.png)
|
||||
skin/classic/browser/customizableui/customize-illustration@2x.png (../shared/customizableui/customize-illustration@2x.png)
|
||||
|
@ -163,6 +166,7 @@
|
|||
skin/classic/browser/settings.svg (../shared/icons/settings.svg)
|
||||
skin/classic/browser/share.svg (../shared/icons/share.svg)
|
||||
skin/classic/browser/sidebars.svg (../shared/icons/sidebars.svg)
|
||||
skin/classic/browser/sidebars-right.svg (../shared/icons/sidebars-right.svg)
|
||||
skin/classic/browser/stop.svg (../shared/icons/stop.svg)
|
||||
skin/classic/browser/sync.svg (../shared/icons/sync.svg)
|
||||
skin/classic/browser/synced-tabs.svg (../shared/icons/synced-tabs.svg)
|
||||
|
|
|
@ -628,7 +628,8 @@
|
|||
border-radius: 3px;
|
||||
margin: 3px;
|
||||
margin-inline-start: 9px;
|
||||
transition: max-width 300ms;
|
||||
transition: max-width 100ms;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.restore-tabs-button:hover {
|
||||
|
@ -660,5 +661,4 @@
|
|||
|
||||
.restore-tabs-button > .toolbarbutton-text {
|
||||
display: -moz-box;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
|
|
@ -194,12 +194,12 @@ toolbar:not([brighttext]) #bookmarks-menu-button[cui-areatype="toolbar"][starred
|
|||
}
|
||||
|
||||
#sidebar-button[cui-areatype="toolbar"] {
|
||||
list-style-image: url("chrome://browser/skin/sidebars.svg");
|
||||
list-style-image: url("chrome://browser/skin/sidebars-right.svg");
|
||||
}
|
||||
|
||||
#sidebar-button[cui-areatype="toolbar"]:-moz-locale-dir(ltr):not([positionend]),
|
||||
#sidebar-button[cui-areatype="toolbar"]:-moz-locale-dir(rtl)[positionend] {
|
||||
transform: scaleX(-1);
|
||||
list-style-image: url("chrome://browser/skin/sidebars.svg");
|
||||
}
|
||||
|
||||
#panic-button[cui-areatype="toolbar"] {
|
||||
|
|
|
@ -121,6 +121,11 @@
|
|||
to { filter: blur(5px) sepia(60%) saturate(30%); }
|
||||
}
|
||||
|
||||
@keyframes anim-filter-drop-shadow {
|
||||
from { filter: drop-shadow(10px 10px 10px rgb(0, 255, 0)); }
|
||||
to { filter: drop-shadow(50px 30px 10px rgb(255, 0, 0)); }
|
||||
}
|
||||
|
||||
@keyframes anim-text-shadow {
|
||||
to { text-shadow: none; }
|
||||
}
|
||||
|
@ -563,15 +568,32 @@ test(function(t) {
|
|||
}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
|
||||
'animations with filter properties and missing keyframes');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.animation = 'anim-filter-drop-shadow 100s';
|
||||
var frames = getKeyframes(div);
|
||||
|
||||
assert_equals(frames.length, 2, "number of frames");
|
||||
|
||||
var expected = [
|
||||
{ offset: 0, computedOffset: 0, easing: "ease",
|
||||
filter: "drop-shadow(10px 10px 10px rgb(0, 255, 0))" },
|
||||
{ offset: 1, computedOffset: 1, easing: "ease",
|
||||
filter: "drop-shadow(50px 30px 10px rgb(255, 0, 0))" },
|
||||
];
|
||||
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
|
||||
}
|
||||
}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
|
||||
'animation with drop-shadow of filter property');
|
||||
|
||||
// Gecko-specific test case: We are specifically concerned here that the
|
||||
// computed value for text-shadow and a "none" specified on a keyframe
|
||||
// are correctly represented.
|
||||
|
||||
test(function(t) {
|
||||
if (!isServoEnabled()) {
|
||||
// FIXME : Bug 1374564 : the serialization of text-shadow is wrong on gecko
|
||||
return;
|
||||
}
|
||||
var div = addDiv(t);
|
||||
|
||||
div.style.textShadow = '1px 1px 2px rgb(0, 0, 0), ' +
|
||||
|
|
|
@ -340,14 +340,3 @@ function addSVGElement(target, tag, attrs) {
|
|||
target.appendChild(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if servo is enabled.
|
||||
*/
|
||||
function isServoEnabled() {
|
||||
try {
|
||||
return SpecialPowers.getBoolPref('layout.css.servo.enabled');
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -453,6 +453,9 @@ class CGDOMJSClass(CGThing):
|
|||
traceHook = 'nullptr'
|
||||
reservedSlots = slotCount
|
||||
if self.descriptor.interface.hasProbablyShortLivingWrapper():
|
||||
if not self.descriptor.wrapperCache:
|
||||
raise TypeError("Need a wrapper cache to support nursery "
|
||||
"allocation of DOM objects")
|
||||
classFlags += " | JSCLASS_SKIP_NURSERY_FINALIZE"
|
||||
|
||||
if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
|
||||
|
@ -12452,6 +12455,22 @@ class CGDOMJSProxyHandler_isCallable(ClassMethod):
|
|||
""")
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_canNurseryAllocate(ClassMethod):
|
||||
"""
|
||||
Override the default canNurseryAllocate in BaseProxyHandler, for cases when
|
||||
we should be nursery-allocated.
|
||||
"""
|
||||
def __init__(self):
|
||||
ClassMethod.__init__(self, "canNurseryAllocate", "bool",
|
||||
[],
|
||||
virtual=True, override=True, const=True)
|
||||
|
||||
def getBody(self):
|
||||
return dedent("""
|
||||
return true;
|
||||
""")
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler(CGClass):
|
||||
def __init__(self, descriptor):
|
||||
assert (descriptor.supportsIndexedProperties() or
|
||||
|
@ -12488,6 +12507,11 @@ class CGDOMJSProxyHandler(CGClass):
|
|||
if descriptor.operations['LegacyCaller']:
|
||||
methods.append(CGDOMJSProxyHandler_call())
|
||||
methods.append(CGDOMJSProxyHandler_isCallable())
|
||||
if descriptor.interface.hasProbablyShortLivingWrapper():
|
||||
if not descriptor.wrapperCache:
|
||||
raise TypeError("Need a wrapper cache to support nursery "
|
||||
"allocation of DOM objects")
|
||||
methods.append(CGDOMJSProxyHandler_canNurseryAllocate())
|
||||
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
parentClass = 'ShadowingDOMProxyHandler'
|
||||
|
|
|
@ -2,7 +2,7 @@ default-preferences pref(dom.forms.number,true) pref(dom.forms.datetime,true)
|
|||
fuzzy-if(skiaContent,1,3) needs-focus == input-load.html input-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus == input-create.html input-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus skip-if(styloVsGecko) == input-number.html input-number-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus fails-if(styloVsGecko) == input-time.html input-time-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus == input-time.html input-time-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus == button-load.html button-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus == button-create.html button-ref.html
|
||||
fuzzy-if(skiaContent,1,3) needs-focus == textarea-load.html textarea-ref.html
|
||||
|
|
|
@ -1520,13 +1520,26 @@ StartMacOSContentSandbox()
|
|||
PR_GetEnv("MOZ_SANDBOX_LOGGING");
|
||||
info.appPath.assign(appPath.get());
|
||||
info.appBinaryPath.assign(appBinaryPath.get());
|
||||
if (developer_repo_dir != nullptr) {
|
||||
info.appDir.assign(developer_repo_dir);
|
||||
} else {
|
||||
info.appDir.assign(appDir.get());
|
||||
}
|
||||
info.appDir.assign(appDir.get());
|
||||
info.appTempDir.assign(tempDirPath.get());
|
||||
|
||||
// These paths are used to whitelist certain directories used by the testing
|
||||
// system. They should not be considered a public API, and are only intended
|
||||
// for use in automation.
|
||||
nsAdoptingCString testingReadPath1 =
|
||||
Preferences::GetCString("security.sandbox.content.mac.testing_read_path1");
|
||||
if (!testingReadPath1.IsEmpty()) {
|
||||
info.testingReadPath1.assign(testingReadPath1.get());
|
||||
}
|
||||
nsAdoptingCString testingReadPath2 =
|
||||
Preferences::GetCString("security.sandbox.content.mac.testing_read_path2");
|
||||
if (!testingReadPath2.IsEmpty()) {
|
||||
info.testingReadPath2.assign(testingReadPath2.get());
|
||||
}
|
||||
if (developer_repo_dir) {
|
||||
info.testingReadPath3.assign(developer_repo_dir);
|
||||
}
|
||||
|
||||
if (profileDir) {
|
||||
info.hasSandboxedProfile = true;
|
||||
info.profileDir.assign(profileDirPath.get());
|
||||
|
|
|
@ -784,7 +784,6 @@ skip-if = toolkit == 'android' # android(bug 1232305)
|
|||
[test_loop.html]
|
||||
skip-if = toolkit == 'android' # bug 1242112, android(bug 1232305)
|
||||
[test_media_selection.html]
|
||||
skip-if = toolkit == 'android' # bug 1372457
|
||||
[test_media_sniffer.html]
|
||||
skip-if = android_version == '15' || android_version == '17' # android(bug 1232305)
|
||||
[test_mediarecorder_avoid_recursion.html]
|
||||
|
|
|
@ -376,6 +376,7 @@ var pedanticChecks = report => {
|
|||
+ stat.framesEncoded);
|
||||
}
|
||||
} else if (stat.type == "candidate-pair") {
|
||||
info("candidate-pair is: " + JSON.stringify(stat));
|
||||
//
|
||||
// Required fields
|
||||
//
|
||||
|
@ -411,7 +412,10 @@ var pedanticChecks = report => {
|
|||
+ stat.writable);
|
||||
|
||||
// state
|
||||
if (stat.state == "succeeded") {
|
||||
if (stat.state == "succeeded" &&
|
||||
stat.selected !== undefined &&
|
||||
stat.selected) {
|
||||
info("candidate-pair state is succeeded and selected is true");
|
||||
// nominated
|
||||
ok(stat.nominated,
|
||||
stat.type + ".nominated is true. value="
|
||||
|
@ -438,10 +442,23 @@ var pedanticChecks = report => {
|
|||
+ stat.lastPacketReceivedTimestamp);
|
||||
|
||||
} else {
|
||||
info("candidate-pair is _not_ both state == succeeded and selected");
|
||||
// nominated
|
||||
ok(!stat.nominated,
|
||||
stat.type + ".nominated is false. value="
|
||||
ok(stat.nominated !== undefined,
|
||||
stat.type + ".nominated exists. value="
|
||||
+ stat.nominated);
|
||||
ok(stat.bytesSent !== undefined,
|
||||
stat.type + ".bytesSent exists. value="
|
||||
+ stat.bytesSent);
|
||||
ok(stat.bytesReceived !== undefined,
|
||||
stat.type + ".bytesReceived exists. value="
|
||||
+ stat.bytesReceived);
|
||||
ok(stat.lastPacketSentTimestamp !== undefined,
|
||||
stat.type + ".lastPacketSentTimestamp exists. value="
|
||||
+ stat.lastPacketSentTimestamp);
|
||||
ok(stat.lastPacketReceivedTimestamp !== undefined,
|
||||
stat.type + ".lastPacketReceivedTimestamp exists. value="
|
||||
+ stat.lastPacketReceivedTimestamp);
|
||||
}
|
||||
|
||||
|
||||
|
@ -450,9 +467,10 @@ var pedanticChecks = report => {
|
|||
//
|
||||
// selected
|
||||
ok(stat.selected === undefined ||
|
||||
((stat.state == "succeeded" && stat.selected == true) ||
|
||||
(stat.selected == false)),
|
||||
stat.type + ".selected is undefined or true. value="
|
||||
((stat.state == "succeeded" && stat.selected) ||
|
||||
!stat.selected),
|
||||
stat.type + ".selected is undefined, true when state is succeeded, "
|
||||
+ "or false. value="
|
||||
+ stat.selected);
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[ProbablyShortLivingWrapper]
|
||||
interface NodeList {
|
||||
getter Node? item(unsigned long index);
|
||||
readonly attribute unsigned long length;
|
||||
|
|
|
@ -168,7 +168,7 @@ void
|
|||
nsXBLPrototypeResources::ComputeServoStyleSet(nsPresContext* aPresContext)
|
||||
{
|
||||
mServoStyleSet.reset(new ServoStyleSet());
|
||||
mServoStyleSet->Init(aPresContext);
|
||||
mServoStyleSet->Init(aPresContext, nullptr);
|
||||
for (StyleSheet* sheet : mStyleSheetList) {
|
||||
MOZ_ASSERT(sheet->IsServo(),
|
||||
"This should only be called with Servo-flavored style backend!");
|
||||
|
|
|
@ -5,16 +5,23 @@
|
|||
#include "TexturePoolOGL.h"
|
||||
#include <stdlib.h> // for malloc
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Monitor.h" // for Monitor, MonitorAutoLock
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_ERROR, etc
|
||||
#include "nsDeque.h" // for nsDeque
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "GeneratedJNINatives.h"
|
||||
#endif
|
||||
|
||||
#define TEXTURE_POOL_SIZE 10
|
||||
static const unsigned int TEXTURE_POOL_SIZE = 10;
|
||||
static const unsigned int TEXTURE_REFILL_THRESHOLD = TEXTURE_POOL_SIZE / 2;
|
||||
|
||||
static mozilla::LazyLogModule gTexturePoolLog("TexturePoolOGL");
|
||||
#define LOG(arg, ...) MOZ_LOG(gTexturePoolLog, mozilla::LogLevel::Debug, ("TexturePoolOGL::%s: " arg, __func__, ##__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
@ -24,6 +31,15 @@ static GLContext* sActiveContext = nullptr;
|
|||
static Monitor* sMonitor = nullptr;
|
||||
static nsDeque* sTextures = nullptr;
|
||||
|
||||
enum class PoolState : uint8_t {
|
||||
NOT_INITIALIZE,
|
||||
INITIALIZED,
|
||||
SHUTDOWN
|
||||
};
|
||||
static PoolState sPoolState = PoolState::NOT_INITIALIZE;
|
||||
|
||||
static bool sHasPendingFillTask = false;
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
class GeckoSurfaceTextureSupport final
|
||||
|
@ -37,9 +53,27 @@ public:
|
|||
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
void TexturePoolOGL::MaybeFillTextures()
|
||||
{
|
||||
if (sTextures->GetSize() < TEXTURE_REFILL_THRESHOLD &&
|
||||
!sHasPendingFillTask) {
|
||||
LOG("need to refill the texture pool.");
|
||||
sHasPendingFillTask = true;
|
||||
MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop();
|
||||
MOZ_ASSERT(loop);
|
||||
loop->PostTask(
|
||||
NS_NewRunnableFunction(
|
||||
"TexturePoolOGL::MaybeFillTextures",
|
||||
[] () {
|
||||
TexturePoolOGL::Fill(sActiveContext);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
GLuint TexturePoolOGL::AcquireTexture()
|
||||
{
|
||||
NS_ASSERTION(sMonitor, "not initialized");
|
||||
MOZ_ASSERT(sPoolState != PoolState::NOT_INITIALIZE, "not initialized");
|
||||
MOZ_ASSERT(sPoolState != PoolState::SHUTDOWN, "should not be called after shutdown");
|
||||
|
||||
MonitorAutoLock lock(*sMonitor);
|
||||
|
||||
|
@ -72,6 +106,9 @@ GLuint TexturePoolOGL::AcquireTexture()
|
|||
delete popped;
|
||||
|
||||
NS_ASSERTION(texture, "Failed to retrieve texture from pool");
|
||||
|
||||
MaybeFillTextures();
|
||||
LOG("remaining textures num = %zu", sTextures->GetSize());
|
||||
}
|
||||
|
||||
return texture;
|
||||
|
@ -93,10 +130,12 @@ static void Clear()
|
|||
|
||||
void TexturePoolOGL::Fill(GLContext* aContext)
|
||||
{
|
||||
NS_ASSERTION(aContext, "NULL GLContext");
|
||||
NS_ASSERTION(sMonitor, "not initialized");
|
||||
MOZ_ASSERT(aContext, "NULL GLContext");
|
||||
MOZ_ASSERT(sPoolState != PoolState::NOT_INITIALIZE, "not initialized");
|
||||
MOZ_ASSERT(sPoolState != PoolState::SHUTDOWN, "should not be called after shutdown");
|
||||
|
||||
MonitorAutoLock lock(*sMonitor);
|
||||
sHasPendingFillTask = false;
|
||||
|
||||
if (sActiveContext != aContext) {
|
||||
Clear();
|
||||
|
@ -116,6 +155,7 @@ void TexturePoolOGL::Fill(GLContext* aContext)
|
|||
sTextures->Push((void*) texture);
|
||||
}
|
||||
|
||||
LOG("fill texture pool to %d", TEXTURE_POOL_SIZE);
|
||||
sMonitor->NotifyAll();
|
||||
}
|
||||
|
||||
|
@ -126,6 +166,7 @@ GLContext* TexturePoolOGL::GetGLContext()
|
|||
|
||||
void TexturePoolOGL::Init()
|
||||
{
|
||||
MOZ_ASSERT(sPoolState != PoolState::INITIALIZED);
|
||||
sMonitor = new Monitor("TexturePoolOGL.sMonitor");
|
||||
sTextures = new nsDeque();
|
||||
|
||||
|
@ -134,10 +175,13 @@ void TexturePoolOGL::Init()
|
|||
GeckoSurfaceTextureSupport::Init();
|
||||
}
|
||||
#endif
|
||||
sPoolState = PoolState::INITIALIZED;
|
||||
}
|
||||
|
||||
void TexturePoolOGL::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(sPoolState == PoolState::INITIALIZED);
|
||||
sPoolState = PoolState::SHUTDOWN;
|
||||
delete sMonitor;
|
||||
delete sTextures;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
|
||||
// Clears all internal data structures in preparation for shutdown
|
||||
static void Shutdown();
|
||||
private:
|
||||
// These methods are used to refill textures to avoid pool becomes dry
|
||||
static void MaybeFillTextures();
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
|
|
@ -713,6 +713,13 @@ CheckProxyFlags()
|
|||
((Flags >> JSCLASS_RESERVED_SLOTS_SHIFT) & JSCLASS_RESERVED_SLOTS_MASK)
|
||||
<= shadow::Object::MAX_FIXED_SLOTS,
|
||||
"ProxyValueArray size must not exceed max JSObject size");
|
||||
|
||||
// Proxies must not have the JSCLASS_SKIP_NURSERY_FINALIZE flag set: they
|
||||
// always have finalizers, and whether they can be nursery allocated is
|
||||
// controlled by the canNurseryAllocate() method on the proxy handler.
|
||||
static_assert(!(Flags & JSCLASS_SKIP_NURSERY_FINALIZE),
|
||||
"Proxies must not use JSCLASS_SKIP_NURSERY_FINALIZE; use "
|
||||
"the canNurseryAllocate() proxy handler method instead.");
|
||||
return Flags;
|
||||
}
|
||||
|
||||
|
|
|
@ -221,6 +221,9 @@ function treatAsSafeArgument(entry, varName, csuName)
|
|||
["Gecko_nsStyleSVG_CopyContextProperties", "aDst", null],
|
||||
["Gecko_nsStyleFont_PrefillDefaultForGeneric", "aFont", null],
|
||||
["Gecko_nsStyleSVG_SetContextPropertiesLength", "aSvg", null],
|
||||
["Gecko_ClearAlternateValues", "aFont", null],
|
||||
["Gecko_AppendAlternateValues", "aFont", null],
|
||||
["Gecko_CopyAlternateValuesFrom", "aDest", null],
|
||||
];
|
||||
for (var [entryMatch, varMatch, csuMatch] of whitelist) {
|
||||
assert(entryMatch || varMatch || csuMatch);
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
var g_foo = "foo";
|
||||
var g_bar = "bar";
|
||||
|
||||
// Define base class with a read-only and a writable data property
|
||||
class Base
|
||||
{
|
||||
}
|
||||
Object.defineProperty(Base.prototype, "foo", { value: "Base", writable: true });
|
||||
Object.defineProperty(Base.prototype, "bar", { value: "Base", writable: false });
|
||||
|
||||
// Test various cases that should throw during SETPROP_SUPER
|
||||
class Derived extends Base
|
||||
{
|
||||
// ECMA-2018 9.1.9.1, step 4.a
|
||||
testReadonly() {
|
||||
super.bar = "Derived";
|
||||
}
|
||||
testReadonlyElem() {
|
||||
super[g_bar] = "Derived";
|
||||
}
|
||||
|
||||
// ECMA-2018 9.1.9.1, step 4.b
|
||||
testPrimitiveReceiver() {
|
||||
super.foo = "Derived";
|
||||
}
|
||||
testPrimitiveReceiverElem() {
|
||||
super[g_foo] = "Derived";
|
||||
}
|
||||
|
||||
// ECMA-2018 9.1.9.1, step 4.d.i
|
||||
testAccessorShadow() {
|
||||
Object.defineProperty(this, "foo", { get: function() { } });
|
||||
super.foo = "Derived";
|
||||
}
|
||||
testAccessorShadowElem() {
|
||||
Object.defineProperty(this, "foo", { get: function() { } });
|
||||
super[g_foo] = "Derived";
|
||||
}
|
||||
|
||||
// ECMA-2018 9.1.9.1, step 4.d.ii
|
||||
testReadonlyShadow() {
|
||||
Object.defineProperty(this, "foo", { writable: false });
|
||||
super.foo = "Derived";
|
||||
}
|
||||
testReadonlyShadowElem() {
|
||||
Object.defineProperty(this, "foo", { writable: false });
|
||||
super[g_foo] = "Derived";
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
var cnt = 0;
|
||||
|
||||
try { new Derived().testReadonly(); } catch(e) { cnt++; }
|
||||
try { new Derived().testReadonlyElem(); } catch(e) { cnt++; }
|
||||
try { Derived.prototype.testPrimitiveReceiver.call(null); } catch(e) { cnt++; }
|
||||
try { Derived.prototype.testPrimitiveReceiverElem.call(null); } catch(e) { cnt++; }
|
||||
try { new Derived().testAccessorShadow(); } catch(e) { cnt++; }
|
||||
try { new Derived().testAccessorShadowElem(); } catch(e) { cnt++; }
|
||||
try { new Derived().testReadonlyShadow(); } catch(e) { cnt++; }
|
||||
try { new Derived().testReadonlyShadowElem(); } catch(e) { cnt++; }
|
||||
|
||||
assertEq(cnt, 8);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
class Base
|
||||
{
|
||||
set setter(val) {
|
||||
this.set_val = val;
|
||||
this.set_this = this;
|
||||
}
|
||||
}
|
||||
Base.prototype.prop = "Base";
|
||||
|
||||
class Derived extends Base
|
||||
{
|
||||
set setter(val) { super.setter = val; }
|
||||
setelem(pname, val) { super[pname] = val; }
|
||||
}
|
||||
|
||||
// Test SETPROP_SUPER invoke setters correctly
|
||||
function testSetterChain() {
|
||||
let d = new Derived();
|
||||
|
||||
for (let i = 0; i < 10; ++i)
|
||||
{
|
||||
d.setter = i;
|
||||
assertEq(d.set_val, i);
|
||||
assertEq(d.set_this, d);
|
||||
}
|
||||
}
|
||||
function testSetterChainElem() {
|
||||
let d = new Derived();
|
||||
|
||||
for (let i = 0; i < 10; ++i)
|
||||
{
|
||||
d.setelem("setter", i);
|
||||
assertEq(d.set_val, i);
|
||||
assertEq(d.set_this, d);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that SETPROP_SUPER modifies |this| and not home object
|
||||
function testSuperSetProp() {
|
||||
let d = new Derived();
|
||||
|
||||
for (let i = 0; i < 10; ++i)
|
||||
{
|
||||
d.prop = i;
|
||||
assertEq(d.prop, i);
|
||||
assertEq(d.hasOwnProperty("prop"), true);
|
||||
assertEq(Derived.prototype.prop, "Base");
|
||||
}
|
||||
}
|
||||
function testSuperSetPropElem() {
|
||||
let d = new Derived();
|
||||
|
||||
for (let i = 0; i < 10; ++i)
|
||||
{
|
||||
d.setelem("prop", i);
|
||||
assertEq(d.prop, i);
|
||||
assertEq(d.hasOwnProperty("prop"), true);
|
||||
assertEq(Derived.prototype.prop, "Base");
|
||||
}
|
||||
}
|
||||
|
||||
testSetterChain();
|
||||
testSetterChainElem();
|
||||
|
||||
testSuperSetProp();
|
||||
testSuperSetPropElem();
|
|
@ -2348,6 +2348,47 @@ BaselineCompiler::emit_JSOP_STRICTSETELEM()
|
|||
return emit_JSOP_SETELEM();
|
||||
}
|
||||
|
||||
typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
|
||||
HandleValue, HandleValue, bool);
|
||||
static const VMFunction SetObjectElementInfo =
|
||||
FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_SETELEM_SUPER()
|
||||
{
|
||||
bool strict = IsCheckStrictOp(JSOp(*pc));
|
||||
|
||||
// Incoming stack is |propval, receiver, obj, rval|. We need to shuffle
|
||||
// stack to leave rval when operation is complete.
|
||||
|
||||
// Pop rval into R0, then load propval into R1 and replace with rval.
|
||||
frame.popRegsAndSync(1);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-3)), R1);
|
||||
masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-3)));
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(Imm32(strict));
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R2);
|
||||
pushArg(R2); // receiver
|
||||
pushArg(R0); // rval
|
||||
pushArg(R1); // propval
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
|
||||
pushArg(R0.scratchReg()); // obj
|
||||
|
||||
if (!callVM(SetObjectElementInfo))
|
||||
return false;
|
||||
|
||||
frame.popn(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_STRICTSETELEM_SUPER()
|
||||
{
|
||||
return emit_JSOP_SETELEM_SUPER();
|
||||
}
|
||||
|
||||
typedef bool (*DeleteElementFn)(JSContext*, HandleValue, HandleValue, bool*);
|
||||
static const VMFunction DeleteElementStrictInfo
|
||||
= FunctionInfo<DeleteElementFn>(DeleteElementJit<true>, "DeleteElementStrict");
|
||||
|
@ -2546,6 +2587,46 @@ BaselineCompiler::emit_JSOP_STRICTSETGNAME()
|
|||
return emit_JSOP_SETPROP();
|
||||
}
|
||||
|
||||
typedef bool (*SetPropertySuperFn)(JSContext*, HandleObject, HandleValue,
|
||||
HandlePropertyName, HandleValue, bool);
|
||||
static const VMFunction SetPropertySuperInfo =
|
||||
FunctionInfo<SetPropertySuperFn>(js::SetPropertySuper, "SetPropertySuper");
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_SETPROP_SUPER()
|
||||
{
|
||||
bool strict = IsCheckStrictOp(JSOp(*pc));
|
||||
|
||||
// Incoming stack is |receiver, obj, rval|. We need to shuffle stack to
|
||||
// leave rval when operation is complete.
|
||||
|
||||
// Pop rval into R0, then load receiver into R1 and replace with rval.
|
||||
frame.popRegsAndSync(1);
|
||||
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
|
||||
masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-2)));
|
||||
|
||||
prepareVMCall();
|
||||
|
||||
pushArg(Imm32(strict));
|
||||
pushArg(R0); // rval
|
||||
pushArg(ImmGCPtr(script->getName(pc)));
|
||||
pushArg(R1); // receiver
|
||||
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
|
||||
pushArg(R0.scratchReg()); // obj
|
||||
|
||||
if (!callVM(SetPropertySuperInfo))
|
||||
return false;
|
||||
|
||||
frame.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_STRICTSETPROP_SUPER()
|
||||
{
|
||||
return emit_JSOP_SETPROP_SUPER();
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_GETPROP()
|
||||
{
|
||||
|
|
|
@ -123,6 +123,8 @@ namespace jit {
|
|||
_(JSOP_DELELEM) \
|
||||
_(JSOP_STRICTDELELEM) \
|
||||
_(JSOP_GETELEM_SUPER) \
|
||||
_(JSOP_SETELEM_SUPER) \
|
||||
_(JSOP_STRICTSETELEM_SUPER) \
|
||||
_(JSOP_IN) \
|
||||
_(JSOP_HASOWN) \
|
||||
_(JSOP_GETGNAME) \
|
||||
|
@ -138,6 +140,8 @@ namespace jit {
|
|||
_(JSOP_DELPROP) \
|
||||
_(JSOP_STRICTDELPROP) \
|
||||
_(JSOP_GETPROP_SUPER) \
|
||||
_(JSOP_SETPROP_SUPER) \
|
||||
_(JSOP_STRICTSETPROP_SUPER) \
|
||||
_(JSOP_LENGTH) \
|
||||
_(JSOP_GETBOUNDNAME) \
|
||||
_(JSOP_GETALIASEDVAR) \
|
||||
|
|
|
@ -2868,18 +2868,14 @@ CASE(JSOP_STRICTSETPROP_SUPER)
|
|||
static_assert(JSOP_SETPROP_SUPER_LENGTH == JSOP_STRICTSETPROP_SUPER_LENGTH,
|
||||
"setprop-super and strictsetprop-super must be the same size");
|
||||
|
||||
|
||||
ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
|
||||
ReservedRooted<JSObject*> obj(&rootObject0, ®S.sp[-2].toObject());
|
||||
ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
|
||||
ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
|
||||
|
||||
ObjectOpResult result;
|
||||
if (!SetProperty(cx, obj, id, rval, receiver, result))
|
||||
goto error;
|
||||
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
|
||||
|
||||
bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETPROP_SUPER;
|
||||
if (!result.checkStrictErrorOrWarning(cx, obj, id, strict))
|
||||
|
||||
if (!SetPropertySuper(cx, obj, receiver, name, rval, strict))
|
||||
goto error;
|
||||
|
||||
REGS.sp[-3] = REGS.sp[-1];
|
||||
|
@ -2953,14 +2949,13 @@ CASE(JSOP_STRICTSETELEM_SUPER)
|
|||
static_assert(JSOP_SETELEM_SUPER_LENGTH == JSOP_STRICTSETELEM_SUPER_LENGTH,
|
||||
"setelem-super and strictsetelem-super must be the same size");
|
||||
|
||||
ReservedRooted<jsid> id(&rootId0);
|
||||
FETCH_ELEMENT_ID(-4, id);
|
||||
ReservedRooted<Value> index(&rootValue1, REGS.sp[-4]);
|
||||
ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
|
||||
ReservedRooted<JSObject*> obj(&rootObject1, ®S.sp[-2].toObject());
|
||||
HandleValue value = REGS.stackHandleAt(-1);
|
||||
|
||||
bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETELEM_SUPER;
|
||||
if (!SetObjectElementOperation(cx, obj, id, value, receiver, strict))
|
||||
if (!SetObjectElement(cx, obj, index, value, receiver, strict))
|
||||
goto error;
|
||||
REGS.sp[-4] = value;
|
||||
REGS.sp -= 3;
|
||||
|
@ -4623,6 +4618,16 @@ js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleV
|
|||
return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!ToPropertyKey(cx, index, &id))
|
||||
return false;
|
||||
return SetObjectElementOperation(cx, obj, id, value, receiver, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc)
|
||||
|
@ -5257,3 +5262,15 @@ js::ThrowInitializedThis(JSContext* cx, AbstractFramePtr frame)
|
|||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_REINIT_THIS);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetPropertySuper(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandlePropertyName name, HandleValue rval, bool strict)
|
||||
{
|
||||
RootedId id(cx, NameToId(name));
|
||||
ObjectOpResult result;
|
||||
if (!SetProperty(cx, obj, id, rval, receiver, result))
|
||||
return false;
|
||||
|
||||
return result.checkStrictErrorOrWarning(cx, obj, id, strict);
|
||||
}
|
||||
|
|
|
@ -438,6 +438,9 @@ SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue
|
|||
bool strict, HandleScript script, jsbytecode* pc);
|
||||
|
||||
bool
|
||||
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict);
|
||||
bool
|
||||
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc);
|
||||
|
||||
|
@ -598,6 +601,10 @@ HomeObjectSuperBase(JSContext* cx, HandleObject homeObj);
|
|||
JSObject*
|
||||
SuperFunOperation(JSContext* cx, HandleObject callee);
|
||||
|
||||
bool
|
||||
SetPropertySuper(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
HandlePropertyName id, HandleValue rval, bool strict);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* vm_Interpreter_h */
|
||||
|
|
|
@ -971,14 +971,7 @@ PresShell::Init(nsIDocument* aDocument,
|
|||
// calling Init, since various subroutines need to find the style set off
|
||||
// the PresContext during initialization.
|
||||
mStyleSet = aStyleSet;
|
||||
mStyleSet->Init(aPresContext);
|
||||
|
||||
// Set up our style rule observer. We don't need to inform a ServoStyleSet
|
||||
// of the binding manager because it gets XBL style sheets from bindings
|
||||
// in a different way.
|
||||
if (mStyleSet->IsGecko()) {
|
||||
mStyleSet->AsGecko()->SetBindingManager(mDocument->BindingManager());
|
||||
}
|
||||
mStyleSet->Init(aPresContext, mDocument->BindingManager());
|
||||
|
||||
// Notify our prescontext that it now has a compatibility mode. Note that
|
||||
// this MUST happen after we set up our style set but before we create any
|
||||
|
|
|
@ -97,20 +97,17 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
|
|||
for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
|
||||
sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
|
||||
}
|
||||
if (styleSet->IsGecko()) {
|
||||
AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
|
||||
styleSet->AsGecko()->AppendAllXBLStyleSheets(xblSheetArray);
|
||||
|
||||
// The XBL stylesheet array will quite often be full of duplicates. Cope:
|
||||
nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
|
||||
for (CSSStyleSheet* sheet : xblSheetArray) {
|
||||
if (!sheetSet.Contains(sheet)) {
|
||||
sheetSet.PutEntry(sheet);
|
||||
sheets.AppendElement(sheet);
|
||||
}
|
||||
AutoTArray<StyleSheet*, 32> xblSheetArray;
|
||||
styleSet->AsGecko()->AppendAllXBLStyleSheets(xblSheetArray);
|
||||
|
||||
// The XBL stylesheet array will quite often be full of duplicates. Cope:
|
||||
nsTHashtable<nsPtrHashKey<StyleSheet>> sheetSet;
|
||||
for (StyleSheet* sheet : xblSheetArray) {
|
||||
if (!sheetSet.Contains(sheet)) {
|
||||
sheetSet.PutEntry(sheet);
|
||||
sheets.AppendElement(sheet);
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("stylo: XBL style sheets not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,11 +83,11 @@ fuzzy-if(gtkWidget,6,26200) == 28811-2b.html 28811-2-ref.html # Bug 1128229
|
|||
== 76331-1.html 76331-1-ref.html
|
||||
== 81947-1.html 81947-ref.html
|
||||
== 82711-1.html 82711-1-ref.html
|
||||
fails-if(styloVsGecko) == 82711-2.html 82711-2-ref.html
|
||||
== 82711-2.html 82711-2-ref.html
|
||||
== 82711-3.html 82711-3-ref.html
|
||||
!= 82711-1-ref.html 82711-2-ref.html
|
||||
!= 82711-1-ref.html 82711-3-ref.html
|
||||
fails-if(styloVsGecko) != 82711-2-ref.html 82711-3-ref.html
|
||||
!= 82711-2-ref.html 82711-3-ref.html
|
||||
fuzzy-if(Android,4,1) == 84400-1.html 84400-1-ref.html
|
||||
fuzzy-if(skiaContent,2,13) == 84400-2.html 84400-2-ref.html
|
||||
== 97777-1.html 97777-1-ref.html
|
||||
|
@ -661,7 +661,7 @@ fails-if(Android) fuzzy-if(skiaContent&&!Android,2,40) == 373381-2.html 373381-2
|
|||
fails-if(Android) random-if(d2d) == 373381-3.html 373381-3-ref.html
|
||||
fails-if(Android) == 373381-4.html 373381-4-ref.html
|
||||
== 373383-1.html 373383-1-ref.html
|
||||
fails-if(styloVsGecko) == 373433-1.html 373433-1-ref.html
|
||||
== 373433-1.html 373433-1-ref.html
|
||||
== 373533-1.xhtml about:blank
|
||||
== 373533-2.xhtml about:blank
|
||||
== 373533-3.xhtml about:blank
|
||||
|
@ -1811,7 +1811,7 @@ fuzzy-if(skiaContent,1,5) == 956513-1.svg 956513-1-ref.svg
|
|||
fuzzy-if(skiaContent,1,80) == 961887-1.html 961887-1-ref.html
|
||||
== 961887-2.html 961887-2-ref.html
|
||||
== 961887-3.html 961887-3-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,3712) fails-if(styloVsGecko||stylo) == 966992-1.html 966992-1-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,3712) == 966992-1.html 966992-1-ref.html
|
||||
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
|
||||
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
|
||||
fuzzy-if(skiaContent,1,123) == 978911-1.svg 978911-1-ref.svg
|
||||
|
@ -1952,7 +1952,7 @@ fuzzy-if(skiaContent,1,1) == 1202512-2.html 1202512-2-ref.html
|
|||
== 1209994-3.html 1209994-3-ref.html
|
||||
== 1209994-4.html 1209994-4-ref.html
|
||||
== 1222226-1.html 1222226-1-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fails-if(styloVsGecko||stylo) == 1226278.html 1226278-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) == 1226278.html 1226278-ref.html
|
||||
== 1230466.html about:blank
|
||||
random-if(gtkWidget) != 1238243-1.html 1238243-1-notref.html # may fail on Linux, depending on Korean fonts available
|
||||
== 1238243-2.html 1238243-2-ref.html
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
a:visited { color: green }
|
||||
input { color: inherit }
|
||||
input::placeholder { color: green }
|
||||
</style>
|
||||
<a href="visited-page.html"><input placeholder="This should be green"></a>
|
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
a:visited { color: green }
|
||||
input { color: inherit }
|
||||
</style>
|
||||
<a href="visited-page.html"><input placeholder="This should be green"></a>
|
|
@ -13,7 +13,7 @@
|
|||
include pagination/reftest.list
|
||||
|
||||
# Tests for cross-axis alignment (align-self / align-items properties)
|
||||
fails fails-if(styloVsGecko) == flexbox-align-self-baseline-horiz-2.xhtml flexbox-align-self-baseline-horiz-2-ref.xhtml # bug 793456, and possibly others
|
||||
fails-if(!styloVsGecko) == flexbox-align-self-baseline-horiz-2.xhtml flexbox-align-self-baseline-horiz-2-ref.xhtml # bug 793456, and possibly others
|
||||
# This one fails on windows R (but not Ru, strangely) and GTK.
|
||||
# On Windows R and GTK, the single-line <label> flex item has a different
|
||||
# background size in test vs. ref
|
||||
|
|
|
@ -88,9 +88,9 @@ fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(f
|
|||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-textarea-contents-at-1.html threshold-textarea-contents-at-1-ref.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-textarea-contents-at-2.html threshold-textarea-contents-at-2-ref.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-input-text-contents-under-1.html threshold-input-text-contents-under-1.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) fails-if(styloVsGecko) == threshold-input-text-contents-under-2.html threshold-input-text-contents-under-2.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-input-text-contents-under-2.html threshold-input-text-contents-under-2.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-input-text-contents-at-1.html threshold-input-text-contents-at-1-ref.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) fails-if(styloVsGecko) == threshold-input-text-contents-at-2.html threshold-input-text-contents-at-2-ref.html
|
||||
fuzzy-if(gtkWidget,1,10) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-input-text-contents-at-2.html threshold-input-text-contents-at-2-ref.html
|
||||
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-select-listbox-contents-under-1.html threshold-select-listbox-contents-under-1.html
|
||||
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-select-listbox-contents-under-2.html threshold-select-listbox-contents-under-2.html
|
||||
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,100) == threshold-select-listbox-contents-at-1.html threshold-select-listbox-contents-at-1-ref.html
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
== bounds-1.html bounds-1-ref.html
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,140,111) == size-1.html size-1-ref.html
|
||||
== size-2.html size-2-ref.html
|
||||
fails-if(styloVsGecko) HTTP(..) == baseline-1.html baseline-1-ref.html
|
||||
HTTP(..) == baseline-1.html baseline-1-ref.html
|
||||
HTTP(..) == centering-1.xul centering-1-ref.xul
|
||||
== dynamic-height-1.xul dynamic-height-1-ref.xul
|
||||
fuzzy-if(skiaContent,1,500) needs-focus == select.html select-ref.html
|
||||
== intrinsic-size.html intrinsic-size-ref.html
|
||||
fails-if(styloVsGecko) == line-height-0.5.html line-height-1.0.html
|
||||
== line-height-0.5.html line-height-1.0.html
|
||||
!= line-height-1.5.html line-height-1.0.html
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
== placeholder-3.html placeholder-overridden-ref.html
|
||||
== placeholder-4.html placeholder-overridden-ref.html
|
||||
== placeholder-5.html placeholder-visible-ref.html
|
||||
fuzzy-if(winWidget,160,10) fuzzy-if(Android,1,1) fuzzy-if(asyncPan&&!layersGPUAccelerated,146,317) fuzzy-if(OSX==1010&&browserIsRemote,1,8) fails-if(styloVsGecko) == placeholder-6.html placeholder-overflow-ref.html
|
||||
fuzzy-if(winWidget,160,10) fuzzy-if(Android,1,1) fuzzy-if(asyncPan&&!layersGPUAccelerated,146,317) fuzzy-if(OSX==1010&&browserIsRemote,1,8) == placeholder-6.html placeholder-overflow-ref.html
|
||||
skip-if(Android&&asyncPan) == placeholder-6-textarea.html placeholder-overflow-textarea-ref.html
|
||||
# needs-focus == placeholder-7.html placeholder-focus-ref.html
|
||||
# needs-focus == placeholder-8.html placeholder-focus-ref.html
|
||||
|
|
|
@ -10,5 +10,5 @@ fuzzy-if(skiaContent,1,1) == rtl.html rtl-dynamic-attr.html
|
|||
fuzzy-if(skiaContent,1,1) == rtl.html rtl-dynamic-style.html
|
||||
== rtl.html in-dynamic-rtl-doc.html
|
||||
fuzzy-if(skiaContent,1,3) == setvalue-framereconstruction-1.html setvalue-framereconstruction-ref.html
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,102,4168) fails-if(styloVsGecko||stylo) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,102,4168) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html
|
||||
== various-cols.html various-cols-ref.html
|
||||
|
|
|
@ -151,7 +151,7 @@ HTTP(..) == zwnj-02.xhtml zwnj-02-ref.xhtml # HTTP(..) for ../filters.svg
|
|||
== initial-zwj-1.html initial-zwj-1-ref.html
|
||||
== cgj-01.html cgj-01-ref.html
|
||||
== 444656.html 444656-ref.html
|
||||
fails-if(styloVsGecko) == 449555-1.html 449555-1-ref.html
|
||||
== 449555-1.html 449555-1-ref.html
|
||||
== 467722.html 467722-ref.html
|
||||
fuzzy-if(skiaContent,1,600) HTTP(..) == 475092-sub.html 475092-ref.html
|
||||
fails-if(Android) fuzzy-if(skiaContent&&!Android,90,3100) HTTP(..) == 475092-pos.html 475092-sub.html # bug 482596
|
||||
|
|
|
@ -247,6 +247,12 @@ Gecko_ElementState(RawGeckoElementBorrowed aElement)
|
|||
return aElement->StyleState().ServoValue();
|
||||
}
|
||||
|
||||
EventStates::ServoType
|
||||
Gecko_DocumentState(const nsIDocument* aDocument)
|
||||
{
|
||||
return aDocument->ThreadSafeGetDocumentState().ServoValue();
|
||||
}
|
||||
|
||||
bool
|
||||
Gecko_IsTextNode(RawGeckoNodeBorrowed aNode)
|
||||
{
|
||||
|
@ -819,7 +825,7 @@ Gecko_GetXMLLangValue(RawGeckoElementBorrowed aElement)
|
|||
}
|
||||
|
||||
nsIDocument::DocumentTheme
|
||||
Gecko_GetDocumentLWTheme(const nsIDocument *aDocument)
|
||||
Gecko_GetDocumentLWTheme(const nsIDocument* aDocument)
|
||||
{
|
||||
return aDocument->ThreadSafeGetDocumentLWTheme();
|
||||
}
|
||||
|
@ -1238,6 +1244,29 @@ Gecko_nsFont_Destroy(nsFont* aDest)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
Gecko_ClearAlternateValues(nsFont* aFont, size_t aLength)
|
||||
{
|
||||
aFont->alternateValues.Clear();
|
||||
aFont->alternateValues.SetCapacity(aLength);
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_AppendAlternateValues(nsFont* aFont, uint32_t aAlternateName, nsIAtom* aAtom)
|
||||
{
|
||||
aFont->alternateValues.AppendElement(gfxAlternateValue {
|
||||
aAlternateName,
|
||||
nsDependentAtomString(aAtom)
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_CopyAlternateValuesFrom(nsFont* aDest, const nsFont* aSrc)
|
||||
{
|
||||
aDest->alternateValues.Clear();
|
||||
aDest->alternateValues.AppendElements(aSrc->alternateValues);
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_SetImageOrientation(nsStyleVisibility* aVisibility,
|
||||
double aRadians, bool aFlip)
|
||||
|
@ -1435,6 +1464,7 @@ Gecko_CreateGradient(uint8_t aShape,
|
|||
uint8_t aSize,
|
||||
bool aRepeating,
|
||||
bool aLegacySyntax,
|
||||
bool aMozLegacySyntax,
|
||||
uint32_t aStopCount)
|
||||
{
|
||||
nsStyleGradient* result = new nsStyleGradient();
|
||||
|
@ -1443,6 +1473,7 @@ Gecko_CreateGradient(uint8_t aShape,
|
|||
result->mSize = aSize;
|
||||
result->mRepeating = aRepeating;
|
||||
result->mLegacySyntax = aLegacySyntax;
|
||||
result->mMozLegacySyntax = aMozLegacySyntax;
|
||||
|
||||
result->mAngle.SetNoneValue();
|
||||
result->mBgPosX.SetNoneValue();
|
||||
|
|
|
@ -154,6 +154,7 @@ void Gecko_LoadStyleSheet(mozilla::css::Loader* loader,
|
|||
|
||||
// Selector Matching.
|
||||
uint64_t Gecko_ElementState(RawGeckoElementBorrowed element);
|
||||
uint64_t Gecko_DocumentState(const nsIDocument* aDocument);
|
||||
bool Gecko_IsTextNode(RawGeckoNodeBorrowed node);
|
||||
bool Gecko_IsRootElement(RawGeckoElementBorrowed element);
|
||||
bool Gecko_MatchesElement(mozilla::CSSPseudoClassType type, RawGeckoElementBorrowed element);
|
||||
|
@ -164,7 +165,7 @@ bool Gecko_MatchLang(RawGeckoElementBorrowed element,
|
|||
nsIAtom* override_lang, bool has_override_lang,
|
||||
const char16_t* value);
|
||||
nsIAtom* Gecko_GetXMLLangValue(RawGeckoElementBorrowed element);
|
||||
nsIDocument::DocumentTheme Gecko_GetDocumentLWTheme(const nsIDocument *aDocument);
|
||||
nsIDocument::DocumentTheme Gecko_GetDocumentLWTheme(const nsIDocument* aDocument);
|
||||
|
||||
// Attributes.
|
||||
#define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
|
||||
|
@ -275,6 +276,11 @@ void Gecko_nsFont_InitSystem(nsFont* dst, int32_t font_id,
|
|||
const nsStyleFont* font, RawGeckoPresContextBorrowed pres_context);
|
||||
void Gecko_nsFont_Destroy(nsFont* dst);
|
||||
|
||||
// Font variant alternates
|
||||
void Gecko_ClearAlternateValues(nsFont* font, size_t length);
|
||||
void Gecko_AppendAlternateValues(nsFont* font, uint32_t alternate_name, nsIAtom* atom);
|
||||
void Gecko_CopyAlternateValuesFrom(nsFont* dest, const nsFont* src);
|
||||
|
||||
// Visibility style
|
||||
void Gecko_SetImageOrientation(nsStyleVisibility* aVisibility,
|
||||
double aRadians,
|
||||
|
@ -312,6 +318,7 @@ nsStyleGradient* Gecko_CreateGradient(uint8_t shape,
|
|||
uint8_t size,
|
||||
bool repeating,
|
||||
bool legacy_syntax,
|
||||
bool moz_legacy_syntax,
|
||||
uint32_t stops);
|
||||
|
||||
// list-style-image style.
|
||||
|
|
|
@ -63,10 +63,11 @@ ServoStyleSet::~ServoStyleSet()
|
|||
}
|
||||
|
||||
void
|
||||
ServoStyleSet::Init(nsPresContext* aPresContext)
|
||||
ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
|
||||
{
|
||||
mPresContext = aPresContext;
|
||||
mRawSet.reset(Servo_StyleSet_Init(aPresContext));
|
||||
mBindingManager = aBindingManager;
|
||||
|
||||
mPresContext->DeviceContext()->InitFontCache();
|
||||
|
||||
|
@ -862,6 +863,14 @@ ServoStyleSet::StyleSheetAt(SheetType aType,
|
|||
return mSheets[aType][aIndex];
|
||||
}
|
||||
|
||||
void
|
||||
ServoStyleSet::AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const
|
||||
{
|
||||
if (mBindingManager) {
|
||||
mBindingManager->AppendAllSheets(aArray);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ServoStyleSet::RemoveDocStyleSheet(ServoStyleSheet* aSheet)
|
||||
{
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
ServoStyleSet();
|
||||
~ServoStyleSet();
|
||||
|
||||
void Init(nsPresContext* aPresContext);
|
||||
void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
|
||||
void BeginShutdown();
|
||||
void Shutdown();
|
||||
|
||||
|
@ -255,6 +255,8 @@ public:
|
|||
int32_t SheetCount(SheetType aType) const;
|
||||
ServoStyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
|
||||
|
||||
void AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const;
|
||||
|
||||
template<typename Func>
|
||||
void EnumerateStyleSheetArrays(Func aCallback) const {
|
||||
for (const auto& sheetArray : mSheets) {
|
||||
|
@ -624,6 +626,9 @@ private:
|
|||
// Constructed lazily when requested by devtools.
|
||||
RefPtr<ServoStyleRuleMap> mStyleRuleMap;
|
||||
|
||||
// This can be null if we are used to hold XBL style sheets.
|
||||
RefPtr<nsBindingManager> mBindingManager;
|
||||
|
||||
static ServoStyleSet* sInServoTraversal;
|
||||
};
|
||||
|
||||
|
|
|
@ -326,7 +326,8 @@ ToPrimitive(nsCSSValue::Array* aArray)
|
|||
|
||||
static void
|
||||
AppendCSSShadowValue(const nsCSSShadowItem *aShadow,
|
||||
nsCSSValueList **&aResultTail)
|
||||
nsCSSValueList **&aResultTail,
|
||||
nsCSSPropertyID aProperty)
|
||||
{
|
||||
MOZ_ASSERT(aShadow, "shadow expected");
|
||||
|
||||
|
@ -335,9 +336,9 @@ AppendCSSShadowValue(const nsCSSShadowItem *aShadow,
|
|||
arr->Item(0).SetIntegerCoordValue(aShadow->mXOffset);
|
||||
arr->Item(1).SetIntegerCoordValue(aShadow->mYOffset);
|
||||
arr->Item(2).SetIntegerCoordValue(aShadow->mRadius);
|
||||
// NOTE: This code sometimes stores mSpread: 0 even when
|
||||
// the parser would be required to leave it null.
|
||||
arr->Item(3).SetIntegerCoordValue(aShadow->mSpread);
|
||||
if (aProperty == eCSSProperty_box_shadow) {
|
||||
arr->Item(3).SetIntegerCoordValue(aShadow->mSpread);
|
||||
}
|
||||
if (aShadow->mHasColor) {
|
||||
arr->Item(4).SetColorValue(aShadow->mColor);
|
||||
}
|
||||
|
@ -886,7 +887,8 @@ GetNumberOrPercent(const nsCSSValue &aValue);
|
|||
static bool
|
||||
ComputeSingleShadowSquareDistance(const nsCSSValueList* aShadow1,
|
||||
const nsCSSValueList* aShadow2,
|
||||
double& aSquareDistance)
|
||||
double& aSquareDistance,
|
||||
nsCSSPropertyID aProperty)
|
||||
{
|
||||
MOZ_ASSERT(aShadow1->mValue.GetUnit() == eCSSUnit_Array, "wrong unit");
|
||||
MOZ_ASSERT(aShadow2->mValue.GetUnit() == eCSSUnit_Array, "wrong unit");
|
||||
|
@ -896,6 +898,11 @@ ComputeSingleShadowSquareDistance(const nsCSSValueList* aShadow1,
|
|||
double squareDistance = 0.0;
|
||||
// X, Y, Radius, Spread
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
// Spread value is not necessary on text-shadow,
|
||||
// so we skip the computing distance.
|
||||
if (i == 3 && (aProperty != eCSSProperty_box_shadow)) {
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(array1->Item(i).GetUnit() == eCSSUnit_Pixel,
|
||||
"unexpected unit");
|
||||
MOZ_ASSERT(array2->Item(i).GetUnit() == eCSSUnit_Pixel,
|
||||
|
@ -1002,7 +1009,8 @@ ComputeFilterSquareDistance(const nsCSSValueList* aList1,
|
|||
"drop-shadow filter func doesn't support lists");
|
||||
if (!ComputeSingleShadowSquareDistance(func1.GetListValue(),
|
||||
func2.GetListValue(),
|
||||
aSquareDistance)) {
|
||||
aSquareDistance,
|
||||
eCSSProperty_filter)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -1793,7 +1801,8 @@ StyleAnimationValue::ComputeDistance(nsCSSPropertyID aProperty,
|
|||
while (shadow1) {
|
||||
double squareDistance = 0.0;
|
||||
if (!ComputeSingleShadowSquareDistance(shadow1, shadow2,
|
||||
squareDistance)) {
|
||||
squareDistance,
|
||||
aProperty)) {
|
||||
NS_ERROR("Unexpected ComputeSingleShadowSquareDistance failure; "
|
||||
"why didn't we fail earlier, in AddWeighted calls above?");
|
||||
}
|
||||
|
@ -2036,7 +2045,8 @@ AppendToCSSValuePairList(UniquePtr<nsCSSValuePairList>& aHead,
|
|||
static UniquePtr<nsCSSValueList>
|
||||
AddWeightedShadowItems(double aCoeff1, const nsCSSValue &aValue1,
|
||||
double aCoeff2, const nsCSSValue &aValue2,
|
||||
ColorAdditionType aColorAdditionType)
|
||||
ColorAdditionType aColorAdditionType,
|
||||
nsCSSPropertyID aProperty)
|
||||
{
|
||||
// X, Y, Radius, Spread, Color, Inset
|
||||
MOZ_ASSERT(aValue1.GetUnit() == eCSSUnit_Array,
|
||||
|
@ -2048,6 +2058,9 @@ AddWeightedShadowItems(double aCoeff1, const nsCSSValue &aValue1,
|
|||
RefPtr<nsCSSValue::Array> resultArray = nsCSSValue::Array::Create(6);
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
// The text-shadow is not need to spread radius,
|
||||
// So we skip this interpolation.
|
||||
if (i == 3 && (aProperty != eCSSProperty_box_shadow)) continue;
|
||||
AddCSSValuePixel(aCoeff1, array1->Item(i), aCoeff2, array2->Item(i),
|
||||
resultArray->Item(i),
|
||||
// blur radius must be nonnegative
|
||||
|
@ -2231,7 +2244,8 @@ AddWeightedFilterFunctionImpl(double aCoeff1, const nsCSSValueList* aList1,
|
|||
funcArg1.GetListValue()->mValue,
|
||||
aCoeff2,
|
||||
funcArg2.GetListValue()->mValue,
|
||||
aColorAdditionType);
|
||||
aColorAdditionType,
|
||||
eCSSProperty_filter);
|
||||
if (!shadowValue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2771,7 +2785,8 @@ AddWeightedShadowList(double aCoeff1,
|
|||
const nsCSSValueList* aShadow1,
|
||||
double aCoeff2,
|
||||
const nsCSSValueList* aShadow2,
|
||||
ColorAdditionType aColorAdditionType)
|
||||
ColorAdditionType aColorAdditionType,
|
||||
nsCSSPropertyID aProperty)
|
||||
{
|
||||
// This is implemented according to:
|
||||
// http://dev.w3.org/csswg/css3-transitions/#animation-of-property-types-
|
||||
|
@ -2783,7 +2798,8 @@ AddWeightedShadowList(double aCoeff1,
|
|||
UniquePtr<nsCSSValueList> shadowValue =
|
||||
AddWeightedShadowItems(aCoeff1, aShadow1->mValue,
|
||||
aCoeff2, aShadow2->mValue,
|
||||
aColorAdditionType);
|
||||
aColorAdditionType,
|
||||
aProperty);
|
||||
if (!shadowValue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2809,7 +2825,7 @@ AddWeightedShadowList(double aCoeff1,
|
|||
UniquePtr<nsCSSValueList> shadowValue =
|
||||
AddWeightedShadowItems(longCoeff, longShadow->mValue,
|
||||
0.0, longShadow->mValue,
|
||||
aColorAdditionType);
|
||||
aColorAdditionType, aProperty);
|
||||
if (!shadowValue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -3179,7 +3195,8 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty,
|
|||
aValue1.GetCSSValueListValue(),
|
||||
aCoeff2,
|
||||
aValue2.GetCSSValueListValue(),
|
||||
ColorAdditionType::Clamped);
|
||||
ColorAdditionType::Clamped,
|
||||
aProperty);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
@ -3332,7 +3349,8 @@ StyleAnimationValue::Accumulate(nsCSSPropertyID aProperty,
|
|||
UniquePtr<nsCSSValueList> resultList =
|
||||
AddWeightedShadowList(1.0, result.GetCSSValueListValue(),
|
||||
aCount, aA.GetCSSValueListValue(),
|
||||
ColorAdditionType::Unclamped);
|
||||
ColorAdditionType::Unclamped,
|
||||
aProperty);
|
||||
if (resultList) {
|
||||
result.SetAndAdoptCSSValueListValue(resultList.release(), eUnit_Shadow);
|
||||
}
|
||||
|
@ -4568,7 +4586,8 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
|
|||
nsCSSShadowArray* shadowArray = filter.GetDropShadow();
|
||||
MOZ_ASSERT(shadowArray->Length() == 1,
|
||||
"expected exactly one shadow");
|
||||
AppendCSSShadowValue(shadowArray->ShadowAt(0), tmpShadowResultTail);
|
||||
AppendCSSShadowValue(shadowArray->ShadowAt(0),
|
||||
tmpShadowResultTail, aProperty);
|
||||
*shadowResult = *tmpShadowValue;
|
||||
} else {
|
||||
// We checked all possible nsStyleFilter types but
|
||||
|
@ -4816,7 +4835,7 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
|
|||
nsAutoPtr<nsCSSValueList> result;
|
||||
nsCSSValueList **resultTail = getter_Transfers(result);
|
||||
for (uint32_t i = 0, i_end = shadowArray->Length(); i < i_end; ++i) {
|
||||
AppendCSSShadowValue(shadowArray->ShadowAt(i), resultTail);
|
||||
AppendCSSShadowValue(shadowArray->ShadowAt(i), resultTail, aProperty);
|
||||
}
|
||||
aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
|
||||
eUnit_Shadow);
|
||||
|
|
|
@ -25,6 +25,7 @@ class Element;
|
|||
class ShadowRoot;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
class nsBindingManager;
|
||||
class nsCSSCounterStyleRule;
|
||||
struct nsFontFaceRuleContainer;
|
||||
class nsIAtom;
|
||||
|
@ -109,7 +110,7 @@ public:
|
|||
// nsStyleSet or ServoStyleSet. See corresponding comments in
|
||||
// nsStyleSet.h for descriptions of these methods.
|
||||
|
||||
inline void Init(nsPresContext* aPresContext);
|
||||
inline void Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager);
|
||||
inline void BeginShutdown();
|
||||
inline void Shutdown();
|
||||
inline bool GetAuthorStyleDisabled() const;
|
||||
|
@ -152,6 +153,7 @@ public:
|
|||
StyleSheet* aReferenceSheet);
|
||||
inline int32_t SheetCount(SheetType aType) const;
|
||||
inline StyleSheet* StyleSheetAt(SheetType aType, int32_t aIndex) const;
|
||||
inline void AppendAllXBLStyleSheets(nsTArray<StyleSheet*>& aArray) const;
|
||||
inline nsresult RemoveDocStyleSheet(StyleSheet* aSheet);
|
||||
inline nsresult AddDocStyleSheet(StyleSheet* aSheet, nsIDocument* aDocument);
|
||||
inline void RecordStyleSheetChange(StyleSheet* aSheet, StyleSheet::ChangeType);
|
||||
|
|