Merge mozilla-central to inbound. r=merge a=merge on a CLOSED TREE

This commit is contained in:
Bogdan Tara 2017-12-04 22:47:53 +02:00
Родитель c4a7977565 d9b3452d66
Коммит 28f65f2044
729 изменённых файлов: 23936 добавлений и 17317 удалений

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

@ -1481,6 +1481,13 @@ AccessibleWrap::GetIAccessibleFor(const VARIANT& aVarChild, bool* aIsDefunct)
// window and the child id points in the content documents. Thus we need to
// make sure that it is never called on proxies.
if (XRE_IsParentProcess() && !IsProxy() && !sIDGen.IsChromeID(varChild.lVal)) {
if (!IsRoot()) {
// Bug 1422201: accChild with a remote id is only valid on the root accessible.
// Otherwise, we might return remote accessibles which aren't descendants
// of this accessible. This would confuse clients which use accChild to
// check whether something is a descendant of a document.
return nullptr;
}
return GetRemoteIAccessibleFor(varChild);
}

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

@ -78,24 +78,24 @@ MAC_BUNDLE_VERSION = $(shell $(PYTHON) $(srcdir)/macversion.py --version=$(MOZ_A
.PHONY: repackage
tools repackage:: $(DIST)/bin/$(MOZ_APP_NAME) features
rm -rf $(dist_dest)
$(MKDIR) -p $(dist_dest)/Contents/MacOS
$(MKDIR) -p $(dist_dest)/$(LPROJ)
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents $(dist_dest) --exclude English.lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(dist_dest)/$(LPROJ)
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' -e 's|%MOZ_DEVELOPER_REPO_PATH%|$(topsrcdir)|' -e 's|%MOZ_DEVELOPER_OBJ_PATH%|$(topobjdir)|' $(srcdir)/macbuild/Contents/Info.plist.in > $(dist_dest)/Contents/Info.plist
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(dist_dest)/$(LPROJ)/InfoPlist.strings
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ $(dist_dest)/Contents/Resources
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ $(dist_dest)/Contents/MacOS
$(RM) $(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) $(dist_dest)/Contents/MacOS
cp -RL $(DIST)/branding/firefox.icns $(dist_dest)/Contents/Resources/firefox.icns
cp -RL $(DIST)/branding/document.icns $(dist_dest)/Contents/Resources/document.icns
$(MKDIR) -p $(dist_dest)/Contents/Library/LaunchServices
$(MKDIR) -p '$(dist_dest)/Contents/MacOS'
$(MKDIR) -p '$(dist_dest)/$(LPROJ)'
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents '$(dist_dest)' --exclude English.lproj
rsync -a --exclude '*.in' $(srcdir)/macbuild/Contents/Resources/English.lproj/ '$(dist_dest)/$(LPROJ)'
sed -e 's/%APP_VERSION%/$(MOZ_APP_VERSION)/' -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' -e 's/%MAC_BUNDLE_VERSION%/$(MAC_BUNDLE_VERSION)/' -e 's|%MOZ_DEVELOPER_REPO_PATH%|$(topsrcdir)|' -e 's|%MOZ_DEVELOPER_OBJ_PATH%|$(topobjdir)|' $(srcdir)/macbuild/Contents/Info.plist.in > '$(dist_dest)/Contents/Info.plist'
sed -e 's/%MAC_APP_NAME%/$(MAC_APP_NAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > '$(dist_dest)/$(LPROJ)/InfoPlist.strings'
rsync -a --exclude-from='$(srcdir)/macbuild/Contents/MacOS-files.in' $(DIST)/bin/ '$(dist_dest)/Contents/Resources'
rsync -a --include-from='$(srcdir)/macbuild/Contents/MacOS-files.in' --exclude '*' $(DIST)/bin/ '$(dist_dest)/Contents/MacOS'
$(RM) '$(dist_dest)/Contents/MacOS/$(MOZ_APP_NAME)'
rsync -aL $(DIST)/bin/$(MOZ_APP_NAME) '$(dist_dest)/Contents/MacOS'
cp -RL $(DIST)/branding/firefox.icns '$(dist_dest)/Contents/Resources/firefox.icns'
cp -RL $(DIST)/branding/document.icns '$(dist_dest)/Contents/Resources/document.icns'
$(MKDIR) -p '$(dist_dest)/Contents/Library/LaunchServices'
ifdef MOZ_UPDATER
mv -f $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater $(dist_dest)/Contents/Library/LaunchServices
ln -s ../../../../Library/LaunchServices/org.mozilla.updater $(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater
mv -f '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater' '$(dist_dest)/Contents/Library/LaunchServices'
ln -s ../../../../Library/LaunchServices/org.mozilla.updater '$(dist_dest)/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater'
endif
printf APPLMOZB > $(dist_dest)/Contents/PkgInfo
printf APPLMOZB > '$(dist_dest)/Contents/PkgInfo'
endif
.PHONY: features

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

@ -582,6 +582,12 @@ pref("privacy.panicButton.enabled", true);
// Time until temporary permissions expire, in ms
pref("privacy.temporary_permission_expire_time_ms", 3600000);
// If Accept-Language should be spoofed by en-US
// 0 - will prompt
// 1 - don't spoof
// 2 - spoof
pref("privacy.spoof_english", 0);
pref("network.proxy.share_proxy_settings", false); // use the same proxy settings for all protocols
// simple gestures support

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

@ -31,7 +31,7 @@
<command id="cmd_pageSetup" oncommand="PrintUtils.showPageSetup();"/>
<command id="cmd_print" oncommand="PrintUtils.printWindow(window.gBrowser.selectedBrowser.outerWindowID, window.gBrowser.selectedBrowser);"/>
<command id="cmd_printPreview" oncommand="PrintUtils.printPreview(PrintPreviewListener);"/>
<command id="cmd_close" oncommand="BrowserCloseTabOrWindow()"/>
<command id="cmd_close" oncommand="BrowserCloseTabOrWindow(event);"/>
<command id="cmd_closeWindow" oncommand="BrowserTryToCloseWindow()"/>
<command id="cmd_toggleMute" oncommand="gBrowser.selectedTab.toggleMuteAudio()"/>
<command id="cmd_CustomizeToolbars" oncommand="gCustomizeMode.enter()"/>

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

@ -34,6 +34,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
E10SUtils: "resource:///modules/E10SUtils.jsm",
ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
LanguagePrompt: "resource://gre/modules/LanguagePrompt.jsm",
LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
Log: "resource://gre/modules/Log.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
@ -1821,6 +1822,8 @@ var gBrowserInit = {
gAccessibilityServiceIndicator.uninit();
LanguagePrompt.uninit();
// Now either cancel delayedStartup, or clean up the services initialized from
// it.
if (this._boundDelayedStartup) {
@ -2284,33 +2287,6 @@ function BrowserOpenTab(event) {
openUILinkIn(BROWSER_NEW_TAB_URL, where, { relatedToCurrent });
}
/* Called from the openLocation dialog. This allows that dialog to instruct
its opener to open a new window and then step completely out of the way.
Anything less byzantine is causing horrible crashes, rather believably,
though oddly only on Linux. */
function delayedOpenWindow(chrome, flags, href, postData) {
// The other way to use setTimeout,
// setTimeout(openDialog, 10, chrome, "_blank", flags, url),
// doesn't work here. The extra "magic" extra argument setTimeout adds to
// the callback function would confuse gBrowserInit.onLoad() by making
// window.arguments[1] be an integer instead of null.
setTimeout(function() { openDialog(chrome, "_blank", flags, href, null, null, postData); }, 10);
}
/* Required because the tab needs time to set up its content viewers and get the load of
the URI kicked off before becoming the active content area. */
function delayedOpenTab(aUrl, aReferrer, aCharset, aPostData, aAllowThirdPartyFixup) {
gBrowser.loadOneTab(aUrl, {
referrerURI: aReferrer,
charset: aCharset,
postData: aPostData,
inBackground: false,
allowThirdPartyFixup: aAllowThirdPartyFixup,
// Bug 1367168: only use systemPrincipal till we can remove that function
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
});
}
var gLastOpenDirectory = {
_lastDir: null,
get path() {
@ -2372,13 +2348,24 @@ function BrowserOpenFileWindow() {
}
}
function BrowserCloseTabOrWindow() {
// If we're not a browser window, just close the window
function BrowserCloseTabOrWindow(event) {
// If we're not a browser window, just close the window.
if (window.location.href != getBrowserURL()) {
closeWindow(true);
return;
}
// Keyboard shortcuts that would close a tab that is pinned select the first
// unpinned tab instead.
if (event &&
(event.ctrlKey || event.metaKey || event.altKey) &&
gBrowser.selectedTab.pinned) {
if (gBrowser.visibleTabs.length > gBrowser._numPinnedTabs) {
gBrowser.tabContainer.selectedIndex = gBrowser._numPinnedTabs;
}
return;
}
// If the current tab is the last one, this will close the window.
gBrowser.removeCurrentTab({animate: true});
}
@ -2915,7 +2902,6 @@ var BrowserOnClick = {
mm.addMessageListener("Browser:OpenCaptivePortalPage", this);
mm.addMessageListener("Browser:SiteBlockedError", this);
mm.addMessageListener("Browser:EnableOnlineMode", this);
mm.addMessageListener("Browser:SendSSLErrorReport", this);
mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
mm.addMessageListener("Browser:ResetSSLPreferences", this);
mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -2930,7 +2916,6 @@ var BrowserOnClick = {
mm.removeMessageListener("Browser:CertExceptionError", this);
mm.removeMessageListener("Browser:SiteBlockedError", this);
mm.removeMessageListener("Browser:EnableOnlineMode", this);
mm.removeMessageListener("Browser:SendSSLErrorReport", this);
mm.removeMessageListener("Browser:SetSSLErrorReportAuto", this);
mm.removeMessageListener("Browser:ResetSSLPreferences", this);
mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
@ -2973,11 +2958,6 @@ var BrowserOnClick = {
msg.target.reload();
}
break;
case "Browser:SendSSLErrorReport":
this.onSSLErrorReport(msg.target,
msg.data.uri,
msg.data.securityInfo);
break;
case "Browser:ResetSSLPreferences":
let prefSSLImpact = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
return prefs.concat(Services.prefs.getChildList(root));
@ -3006,23 +2986,6 @@ var BrowserOnClick = {
}
},
onSSLErrorReport(browser, uri, securityInfo) {
if (!Services.prefs.getBoolPref("security.ssl.errorReporting.enabled")) {
Cu.reportError("User requested certificate error report sending, but certificate error reporting is disabled");
return;
}
let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
.getService(Ci.nsISerializationHelper);
let transportSecurityInfo = serhelper.deserializeObject(securityInfo);
transportSecurityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
let errorReporter = Cc["@mozilla.org/securityreporter;1"]
.getService(Ci.nsISecurityReporter);
errorReporter.reportTLSError(transportSecurityInfo,
uri.host, uri.port);
},
onCertError(browser, elementId, isTopFrame, location, securityInfoAsString) {
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
let securityInfo;
@ -3526,15 +3489,6 @@ var PrintPreviewListener = {
},
};
function getMarkupDocumentViewer() {
return gBrowser.markupDocumentViewer;
}
// This function is obsolete. Newer code should use <tooltip page="true"/> instead.
function FillInHTMLTooltip(tipElement) {
document.getElementById("aHTMLTooltip").fillInPageTooltip(tipElement);
}
var browserDragAndDrop = {
canDropLink: aEvent => Services.droppedLinkHandler.canDropLink(aEvent, true),
@ -6318,20 +6272,6 @@ var gPageStyleMenu = {
},
};
/* Legacy global page-style functions */
var stylesheetFillPopup = gPageStyleMenu.fillPopup.bind(gPageStyleMenu);
function stylesheetSwitchAll(contentWindow, title) {
// We ignore the contentWindow param. Add-ons don't appear to use
// it, and it's difficult to support in e10s (where it will be a
// CPOW).
gPageStyleMenu.switchStyleSheet(title);
}
function setStyleDisabled(disabled) {
if (disabled)
gPageStyleMenu.disableStyle();
}
var LanguageDetectionListener = {
init() {
window.messageManager.addMessageListener("Translation:DocumentState", msg => {

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

@ -442,14 +442,20 @@ var AboutNetAndCertErrorListener = {
automatic: evt.detail
});
// if we're enabling reports, send a report for this failure
// If we're enabling reports, send a report for this failure.
if (evt.detail) {
let {host, port} = content.document.mozDocumentURIIfNotForErrorPages;
sendAsyncMessage("Browser:SendSSLErrorReport", {
uri: { host, port },
securityInfo: getSerializedSecurityInfo(docShell),
});
let win = evt.originalTarget.ownerGlobal;
let docShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let {securityInfo} = docShell.failedChannel;
securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
let {host, port} = win.document.mozDocumentURIIfNotForErrorPages;
let errorReporter = Cc["@mozilla.org/securityreporter;1"]
.getService(Ci.nsISecurityReporter);
errorReporter.reportTLSError(securityInfo, host, port);
}
},
};

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

@ -211,42 +211,6 @@
]]></body>
</method>
<method name="_setCloseKeyState">
<parameter name="aEnabled"/>
<body><![CDATA[
let keyClose = document.getElementById("key_close");
let closeKeyEnabled = keyClose.getAttribute("disabled") != "true";
if (closeKeyEnabled == aEnabled)
return;
if (aEnabled)
keyClose.removeAttribute("disabled");
else
keyClose.setAttribute("disabled", "true");
// We also want to remove the keyboard shortcut from the file menu
// when the shortcut is disabled, and bring it back when it's
// renabled.
//
// Fixing bug 630826 could make that happen automatically.
// Fixing bug 630830 could avoid the ugly hack below.
let closeMenuItem = document.getElementById("menu_close");
let parentPopup = closeMenuItem.parentNode;
let nextItem = closeMenuItem.nextSibling;
let clonedItem = closeMenuItem.cloneNode(true);
parentPopup.removeChild(closeMenuItem);
if (aEnabled)
clonedItem.setAttribute("key", "key_close");
else
clonedItem.removeAttribute("key");
parentPopup.insertBefore(clonedItem, nextItem);
]]></body>
</method>
<method name="pinTab">
<parameter name="aTab"/>
<body><![CDATA[
@ -264,9 +228,6 @@
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: true });
if (aTab.selected)
this._setCloseKeyState(false);
let event = document.createEvent("Events");
event.initEvent("TabPinned", true, false);
aTab.dispatchEvent(event);
@ -288,9 +249,6 @@
this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: false });
if (aTab.selected)
this._setCloseKeyState(true);
let event = document.createEvent("Events");
event.initEvent("TabUnpinned", true, false);
aTab.dispatchEvent(event);
@ -1371,8 +1329,6 @@
true, false);
}
this._setCloseKeyState(!this.mCurrentTab.pinned);
// TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
// that might rely upon the other changes suppressed.
// Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
@ -4427,16 +4383,26 @@
let {tabParent} = browser.frameLoader;
if (state == this.STATE_LOADING) {
this.assert(!this.minimizedOrFullyOccluded);
browser.docShellIsActive = true;
if (!tabParent) {
if (!this.tabbrowser.tabWarmingEnabled) {
browser.docShellIsActive = true;
}
if (tabParent) {
browser.renderLayers = true;
} else {
this.onLayersReady(browser);
}
} else if (state == this.STATE_UNLOADING) {
this.unwarmTab(tab);
// Setting the docShell to be inactive will also cause it
// to stop rendering layers.
browser.docShellIsActive = false;
if (!tabParent) {
this.onLayersCleared(browser);
}
} else if (state == this.STATE_LOADED) {
this.maybeActivateDocShell(tab);
}
if (!tab.linkedBrowser.isRemoteBrowser) {
@ -4461,11 +4427,6 @@
init() {
this.log("START");
// If we minimized the window before the switcher was activated,
// we might have set the preserveLayers flag for the current
// browser. Let's clear it.
this.tabbrowser.mCurrentBrowser.preserveLayers(false);
window.addEventListener("MozAfterPaint", this);
window.addEventListener("MozLayerTreeReady", this);
window.addEventListener("MozLayerTreeCleared", this);
@ -4475,16 +4436,30 @@
window.addEventListener("SwapDocShells", this, true);
window.addEventListener("EndSwapDocShells", this, true);
let tab = this.requestedTab;
let browser = tab.linkedBrowser;
let tabIsLoaded = !browser.isRemoteBrowser ||
browser.frameLoader.tabParent.hasPresented;
let initialTab = this.requestedTab;
if (!this.minimizedOrFullyOccluded) {
this.log("Initial tab is loaded?: " + tabIsLoaded);
this.setTabState(tab, tabIsLoaded ? this.STATE_LOADED
: this.STATE_LOADING);
for (let tab of this.tabbrowser.tabs) {
if (tab == initialTab && this.minimizedOrFullyOccluded) {
continue;
}
if (tab.linkedPanel) {
let b = tab.linkedBrowser;
let state;
if (b.renderLayers && b.hasLayers) {
state = this.STATE_LOADED;
} else if (b.renderLayers && !b.hasLayers) {
state = this.STATE_LOADING;
} else if (!b.renderLayers && b.hasLayers) {
state = this.STATE_UNLOADING;
} else {
state = this.STATE_UNLOADED;
}
this.setTabState(tab, state);
}
}
this.logState("Tab states initialized");
},
destroy() {
@ -4663,6 +4638,8 @@
} else {
this.tabbrowser._adjustFocusAfterTabSwitch(showTab);
}
this.maybeActivateDocShell(this.requestedTab);
}
}
@ -4701,6 +4678,29 @@
this.setTabState(this.requestedTab, this.STATE_LOADING);
},
maybeActivateDocShell(tab) {
// If we've reached the point where the requested tab has entered
// the loaded state, but the DocShell is still not yet active, we
// should activate it.
let browser = tab.linkedBrowser;
let state = this.getTabState(tab);
let canCheckDocShellState = !browser.mDestroyed &&
(browser.docShell ||
browser.frameLoader.tabParent);
if (tab == this.requestedTab &&
canCheckDocShellState &&
state == this.STATE_LOADED &&
!browser.docShellIsActive &&
!this.minimizedOrFullyOccluded) {
browser.docShellIsActive = true;
this.logState("Set requested tab docshell to active and preserveLayers to false");
// If we minimized the window before the switcher was activated,
// we might have set the preserveLayers flag for the current
// browser. Let's clear it.
browser.preserveLayers(false);
}
},
// This function runs before every event. It fixes up the state
// to account for closed tabs.
preActions() {
@ -4869,6 +4869,13 @@
// Fires when the layers become available for a tab.
onLayersReady(browser) {
let tab = this.tabbrowser.getTabForBrowser(browser);
if (!tab) {
// We probably got a layer update from a tab that got before
// the switcher was created, or for browser that's not being
// tracked by the async tab switcher (like the preloaded about:newtab).
return;
}
this.logState(`onLayersReady(${tab._tPos}, ${browser.isRemoteBrowser})`);
this.assert(this.getTabState(tab) == this.STATE_LOADING ||
@ -5014,7 +5021,12 @@
activateBrowserForPrintPreview(browser) {
let tab = this.tabbrowser.getTabForBrowser(browser);
this.setTabState(tab, this.STATE_LOADING);
let state = this.getTabState(tab);
if (state != this.STATE_LOADING &&
state != this.STATE_LOADED) {
this.setTabState(tab, this.STATE_LOADING);
this.logState("Activated browser " + this.tinfo(tab) + " for print preview");
}
},
canWarmTab(tab) {

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

@ -216,8 +216,6 @@ skip-if = toolkit != "cocoa" # Because of tests for supporting pasting from Serv
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug579872.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug580638.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug580956.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_bug581242.js]
@ -382,8 +380,6 @@ support-files = test_offline_gzip.html gZipOfflineChild.cacheManifest gZipOfflin
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_page_style_menu_update.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_pinnedTabs.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_plainTextLinks.js]
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
[browser_printpreview.js]

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

@ -1,59 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function test() {
waitForExplicitFinish();
function testState(aPinned) {
function elemAttr(id, attr) {
return document.getElementById(id).getAttribute(attr);
}
if (aPinned) {
is(elemAttr("key_close", "disabled"), "true",
"key_close should be disabled when a pinned-tab is selected");
is(elemAttr("menu_close", "key"), "",
"menu_close shouldn't have a key set when a pinned is selected");
} else {
is(elemAttr("key_close", "disabled"), "",
"key_closed shouldn't have disabled state set when a non-pinned tab is selected");
is(elemAttr("menu_close", "key"), "key_close",
"menu_close should have key_close set as its key when a non-pinned tab is selected");
}
}
let lastSelectedTab = gBrowser.selectedTab;
ok(!lastSelectedTab.pinned, "We should have started with a regular tab selected");
testState(false);
let pinnedTab = BrowserTestUtils.addTab(gBrowser, "about:blank");
gBrowser.pinTab(pinnedTab);
// Just pinning the tab shouldn't change the key state.
testState(false);
// Test updating key state after selecting a tab.
gBrowser.selectedTab = pinnedTab;
testState(true);
gBrowser.selectedTab = lastSelectedTab;
testState(false);
gBrowser.selectedTab = pinnedTab;
testState(true);
// Test updating the key state after un/pinning the tab.
gBrowser.unpinTab(pinnedTab);
testState(false);
gBrowser.pinTab(pinnedTab);
testState(true);
// Test updating the key state after removing the tab.
gBrowser.removeTab(pinnedTab);
testState(false);
finish();
}

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

@ -20,6 +20,9 @@ var gExceptionPaths = [
"resource://gre/defaults/pref/",
"resource://shield-recipe-client/node_modules/jexl/lib/",
// These resources are referenced using relative paths from html files.
"resource://payments/",
// https://github.com/mozilla/normandy/issues/577
"resource://shield-recipe-client/test/",

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

@ -20,6 +20,8 @@ skip-if = !e10s # Test only relevant for e10s.
skip-if = !e10s # Pref and test only relevant for e10s.
[browser_opened_file_tab_navigated_to_web.js]
[browser_overflowScroll.js]
[browser_pinnedTabs.js]
[browser_pinnedTabs_closeByKeyboard.js]
[browser_positional_attributes.js]
[browser_preloadedBrowser_zoom.js]
[browser_reload_deleted_file.js]

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

@ -0,0 +1,62 @@
/* 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/. */
function test() {
waitForExplicitFinish();
function testState(aPinned) {
function elemAttr(id, attr) {
return document.getElementById(id).getAttribute(attr);
}
is(elemAttr("key_close", "disabled"), "",
"key_closed should always be enabled");
is(elemAttr("menu_close", "key"), "key_close",
"menu_close should always have key_close set");
}
let unpinnedTab = gBrowser.selectedTab;
ok(!unpinnedTab.pinned, "We should have started with a regular tab selected");
testState(false);
let pinnedTab = gBrowser.addTab();
gBrowser.pinTab(pinnedTab);
// Just pinning the tab shouldn't change the key state.
testState(false);
// Test key state after selecting a tab.
gBrowser.selectedTab = pinnedTab;
testState(true);
gBrowser.selectedTab = unpinnedTab;
testState(false);
gBrowser.selectedTab = pinnedTab;
testState(true);
// Test the key state after un/pinning the tab.
gBrowser.unpinTab(pinnedTab);
testState(false);
gBrowser.pinTab(pinnedTab);
testState(true);
// Test that accel+w in a pinned tab selects the next tab.
let pinnedTab2 = gBrowser.addTab();
gBrowser.pinTab(pinnedTab2);
gBrowser.selectedTab = pinnedTab;
EventUtils.synthesizeKey("w", { accelKey: true });
is(gBrowser.tabs.length, 3, "accel+w in a pinned tab didn't close it");
is(gBrowser.selectedTab, unpinnedTab, "accel+w in a pinned tab selected the first unpinned tab");
// Test the key state after removing the tab.
gBrowser.removeTab(pinnedTab);
gBrowser.removeTab(pinnedTab2);
testState(false);
finish();
}

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

@ -3,7 +3,10 @@
/* global gBrowser SessionStore */
"use strict";
let lazyTabState = {entries: [{url: "http://example.com/", title: "Example Domain"}]};
const {Utils} = Cu.import("resource://gre/modules/sessionstore/Utils.jsm", {});
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
let lazyTabState = {entries: [{url: "http://example.com/", triggeringPrincipal_base64, title: "Example Domain"}]};
add_task(async function test_discarded() {
let extension = ExtensionTestUtils.loadExtension({

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

@ -1,10 +1,13 @@
"use strict";
const {Utils} = Cu.import("resource://gre/modules/sessionstore/Utils.jsm", {});
const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
const SESSION = {
windows: [{
tabs: [
{entries: [{url: "about:blank"}]},
{entries: [{url: "https://example.com/"}]},
{entries: [{url: "about:blank", triggeringPrincipal_base64}]},
{entries: [{url: "https://example.com/", triggeringPrincipal_base64}]},
],
}],
};

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

@ -41,6 +41,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
Integration: "resource://gre/modules/Integration.jsm",
L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
LanguagePrompt: "resource://gre/modules/LanguagePrompt.jsm",
LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
@ -1166,6 +1167,10 @@ BrowserGlue.prototype = {
JawsScreenReaderVersionCheck.onWindowsRestored();
});
}
Services.tm.idleDispatchToMainThread(() => {
LanguagePrompt.init();
});
},
/**

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

@ -27,6 +27,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "formAutofillParent",
"resource://formautofill/FormAutofillParent.jsm");
var gLastHash = "";
@ -174,17 +176,19 @@ function gotoPref(aCategory) {
categories.clearSelection();
}
window.history.replaceState(category, document.title);
search(category, "data-category", subcategory, "data-subcategory");
search(category, "data-category");
let mainContent = document.querySelector(".main-content");
mainContent.scrollTop = 0;
spotlight(subcategory);
Services.telemetry
.getHistogramById("FX_PREFERENCES_CATEGORY_OPENED_V2")
.add(telemetryBucketForCategory(friendlyName));
}
function search(aQuery, aAttribute, aSubquery, aSubAttribute) {
function search(aQuery, aAttribute) {
let mainPrefPane = document.getElementById("mainPrefPane");
let elements = mainPrefPane.children;
for (let element of elements) {
@ -196,14 +200,7 @@ function search(aQuery, aAttribute, aSubquery, aSubAttribute) {
element.getAttribute("data-subpanel") == "true") {
let attributeValue = element.getAttribute(aAttribute);
if (attributeValue == aQuery) {
if (!element.classList.contains("header") &&
element.localName !== "preferences" &&
aSubquery && aSubAttribute) {
let subAttributeValue = element.getAttribute(aSubAttribute);
element.hidden = subAttributeValue != aSubquery;
} else {
element.hidden = false;
}
element.hidden = false;
} else {
element.hidden = true;
}
@ -221,6 +218,106 @@ function search(aQuery, aAttribute, aSubquery, aSubAttribute) {
}
}
async function spotlight(subcategory) {
let highlightedElements = document.querySelectorAll(".spotlight");
if (highlightedElements.length) {
for (let element of highlightedElements) {
element.classList.remove("spotlight");
}
}
if (subcategory) {
if (!gSearchResultsPane.categoriesInitialized) {
await waitForSystemAddonInjectionsFinished([{
isGoingToInject: formAutofillParent.initialized,
elementId: "formAutofillGroup",
}]);
}
scrollAndHighlight(subcategory);
}
/**
* Wait for system addons finished their dom injections.
* @param {Array} addons - The system addon information array.
* For example, the element is looked like
* { isGoingToInject: true, elementId: "formAutofillGroup" }.
* The `isGoingToInject` means the system addon will be visible or not,
* and the `elementId` means the id of the element will be injected into the dom
* if the `isGoingToInject` is true.
* @returns {Promise} Will resolve once all injections are finished.
*/
function waitForSystemAddonInjectionsFinished(addons) {
return new Promise(resolve => {
let elementIdSet = new Set();
for (let addon of addons) {
if (addon.isGoingToInject) {
elementIdSet.add(addon.elementId);
}
}
if (elementIdSet.size) {
let observer = new MutationObserver(mutations => {
for (let mutation of mutations) {
for (let node of mutation.addedNodes) {
elementIdSet.delete(node.id);
if (elementIdSet.size === 0) {
observer.disconnect();
resolve();
}
}
}
});
let mainContent = document.querySelector(".main-content");
observer.observe(mainContent, {childList: true, subtree: true});
// Disconnect the mutation observer once there is any user input.
mainContent.addEventListener("scroll", disconnectMutationObserver);
window.addEventListener("mousedown", disconnectMutationObserver);
window.addEventListener("keydown", disconnectMutationObserver);
function disconnectMutationObserver() {
mainContent.removeEventListener("scroll", disconnectMutationObserver);
window.removeEventListener("mousedown", disconnectMutationObserver);
window.removeEventListener("keydown", disconnectMutationObserver);
observer.disconnect();
}
} else {
resolve();
}
});
}
}
function scrollAndHighlight(subcategory) {
let element = document.querySelector(`[data-subcategory="${subcategory}"]`);
if (element) {
let header = getClosestDisplayedHeader(element);
scrollContentTo(header);
element.classList.add("spotlight");
}
}
/**
* If there is no visible second level header it will return first level header,
* otherwise return second level header.
* @returns {Element} - The closest displayed header.
*/
function getClosestDisplayedHeader(element) {
let header = element.closest("groupbox");
let searchHeader = header.querySelector("caption.search-header");
if (searchHeader && searchHeader.hidden &&
header.previousSibling.classList.contains("subcategory")) {
header = header.previousSibling;
}
return header;
}
function scrollContentTo(element) {
const SEARCH_CONTAINER_HEIGHT = document.querySelector(".search-container").clientHeight;
let mainContent = document.querySelector(".main-content");
let top = element.getBoundingClientRect().top - SEARCH_CONTAINER_HEIGHT;
mainContent.scroll({
top,
behavior: "smooth",
});
}
function helpButtonCommand() {
let pane = history.state;
let categories = document.getElementById("categories");

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

@ -707,20 +707,19 @@
<hbox id="dataCollectionCategory"
class="subcategory"
hidden="true"
data-category="panePrivacy"
data-subcategory="reports">
data-category="panePrivacy">
<label class="header-name" flex="1">&dataCollection.label;</label>
</hbox>
<!-- Firefox Data Collection and Use -->
#ifdef MOZ_DATA_REPORTING
<groupbox id="dataCollectionGroup" data-category="panePrivacy" data-subcategory="reports" hidden="true">
<groupbox id="dataCollectionGroup" data-category="panePrivacy" hidden="true">
<caption class="search-header" hidden="true"><label>&dataCollection.label;</label></caption>
<vbox>
<description>
<label class="tail-with-learn-more">&dataCollectionDesc.label;</label><label id="dataCollectionPrivacyNotice" class="learnMore text-link">&dataCollectionPrivacyNotice.label;</label>
</description>
<description>
<label class="tail-with-learn-more">&dataCollectionDesc.label;</label><label id="dataCollectionPrivacyNotice" class="learnMore text-link">&dataCollectionPrivacyNotice.label;</label>
</description>
<vbox data-subcategory="reports">
<description flex="1">
<checkbox id="submitHealthReportBox" label="&enableHealthReport2.label;"
class="tail-with-learn-more"
@ -731,18 +730,19 @@
#ifndef MOZ_TELEMETRY_REPORTING
<description id="TelemetryDisabledDesc" class="indent tip-caption" control="telemetryGroup">&healthReportingDisabled.label;</description>
#endif
</vbox>
#ifdef MOZ_CRASHREPORTER
<hbox align="center">
<checkbox id="automaticallySubmitCrashesBox"
class="tail-with-learn-more"
preference="browser.crashReports.unsubmittedCheck.autoSubmit"
label="&alwaysSubmitCrashReports1.label;"
accesskey="&alwaysSubmitCrashReports1.accesskey;"/>
<label id="crashReporterLearnMore"
class="learnMore text-link">&crashReporterLearnMore.label;</label>
</hbox>
<hbox align="center">
<checkbox id="automaticallySubmitCrashesBox"
class="tail-with-learn-more"
preference="browser.crashReports.unsubmittedCheck.autoSubmit"
label="&alwaysSubmitCrashReports1.label;"
accesskey="&alwaysSubmitCrashReports1.accesskey;"/>
<label id="crashReporterLearnMore"
class="learnMore text-link">&crashReporterLearnMore.label;</label>
</hbox>
#endif
</vbox>
</groupbox>
#endif

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

@ -73,6 +73,7 @@ skip-if = e10s
[browser_siteData.js]
[browser_siteData2.js]
[browser_siteData3.js]
[browser_spotlight.js]
[browser_site_login_exceptions.js]
[browser_permissions_dialog.js]
[browser_cookies_dialog.js]

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

@ -56,7 +56,6 @@ const mockUpdateManager = {
name: "Firefox Developer Edition 49.0a2",
statusText: "The Update was successfully installed",
buildID: "20160728004010",
type: "minor",
installDate: 1469763105156,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
},
@ -64,7 +63,6 @@ const mockUpdateManager = {
name: "Firefox Developer Edition 43.0a2",
statusText: "The Update was successfully installed",
buildID: "20150929004011",
type: "minor",
installDate: 1443585886224,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
},
@ -72,7 +70,6 @@ const mockUpdateManager = {
name: "Firefox Developer Edition 42.0a2",
statusText: "The Update was successfully installed",
buildID: "20150920004018",
type: "major",
installDate: 1442818147544,
detailsURL: "https://www.mozilla.org/firefox/aurora/"
}
@ -146,7 +143,6 @@ add_task(async function() {
updateData = mockUpdateManager.getUpdateAt(i);
is(update.name, updateData.name + " (" + updateData.buildID + ")", "Wrong update name");
is(update.type, updateData.type == "major" ? "New Version" : "Security Update", "Wrong update type");
is(update.installDate, formatInstallDate(updateData.installDate), "Wrong update installDate");
is(update.detailsURL, updateData.detailsURL, "Wrong update detailsURL");
is(update.status, updateData.statusText, "Wrong update status");

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

@ -25,7 +25,8 @@ add_task(async function() {
is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default");
let doc = gBrowser.contentDocument;
is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
ok(doc.querySelector("#locationBarGroup").hidden, "Location Bar prefs should be hidden when only Reports are requested");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"), "Wait for the reports section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "reports", "The reports section is spotlighted.");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
@ -43,7 +44,8 @@ add_task(async function() {
let selectedPane = gBrowser.contentWindow.history.state;
is(selectedPane, "panePrivacy", "Privacy pane should be selected");
is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
ok(doc.querySelector("#locationBarGroup").hidden, "Location Bar prefs should be hidden when only Reports are requested");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"), "Wait for the reports section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "reports", "The reports section is spotlighted.");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

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

@ -0,0 +1,37 @@
/* eslint-disable mozilla/no-cpows-in-tests */
add_task(async function test_reports_section() {
let prefs = await openPreferencesViaOpenPreferencesAPI("privacy-reports", {leaveOpen: true});
is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default");
let doc = gBrowser.contentDocument;
is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"),
"Wait for the reports section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "reports",
"The reports section is spotlighted.");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(async function test_address_autofill_section() {
let prefs = await openPreferencesViaOpenPreferencesAPI("privacy-address-autofill", {leaveOpen: true});
is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default");
let doc = gBrowser.contentDocument;
is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"),
"Wait for the ddress-autofill section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "address-autofill",
"The ddress-autofill section is spotlighted.");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(async function test_credit_card_autofill_section() {
let prefs = await openPreferencesViaOpenPreferencesAPI("privacy-credit-card-autofill", {leaveOpen: true});
is(prefs.selectedPane, "panePrivacy", "Privacy pane is selected by default");
let doc = gBrowser.contentDocument;
is(doc.location.hash, "#privacy", "The subcategory should be removed from the URI");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"),
"Wait for the credit-card-autofill section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "credit-card-autofill",
"The credit-card-autofill section is spotlighted.");
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

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

@ -3,6 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/Services.jsm");
var gLanguagesDialog = {
_availableLanguagesList: [],
@ -149,6 +151,10 @@ var gLanguagesDialog = {
this._activeLanguages.selectedIndex = selectedIndex;
}
// Update states of accept-language list and buttons according to
// privacy.resistFingerprinting and privacy.spoof_english.
this.readSpoofEnglish();
return undefined;
},
@ -157,8 +163,10 @@ var gLanguagesDialog = {
},
onAvailableLanguageSelect() {
var availableLanguages = this._availableLanguages;
var addButton = document.getElementById("addButton");
addButton.disabled = false;
addButton.disabled = availableLanguages.disabled ||
availableLanguages.selectedIndex < 0;
this._availableLanguages.removeAttribute("accesskey");
},
@ -291,6 +299,40 @@ var gLanguagesDialog = {
downButton.disabled = true;
removeButton.disabled = false;
}
},
readSpoofEnglish() {
var checkbox = document.getElementById("spoofEnglish");
var resistFingerprinting = Services.prefs.getBoolPref("privacy.resistFingerprinting");
if (!resistFingerprinting) {
checkbox.hidden = true;
return false;
}
var spoofEnglish = document.getElementById("privacy.spoof_english").value;
var activeLanguages = this._activeLanguages;
var availableLanguages = this._availableLanguages;
checkbox.hidden = false;
switch (spoofEnglish) {
case 1: // don't spoof intl.accept_lanauges
activeLanguages.disabled = false;
activeLanguages.selectItem(activeLanguages.firstChild);
availableLanguages.disabled = false;
this.onAvailableLanguageSelect();
return false;
case 2: // spoof intl.accept_lanauges
activeLanguages.clearSelection();
activeLanguages.disabled = true;
availableLanguages.disabled = true;
this.onAvailableLanguageSelect();
return true;
default: // will prompt for spoofing intl.accept_lanauges if resisting fingerprinting
return false;
}
},
writeSpoofEnglish() {
return document.getElementById("spoofEnglish").checked ? 2 : 1;
}
};

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

@ -40,6 +40,9 @@
<preference id="pref.browser.language.disable_button.remove"
name="pref.browser.language.disable_button.remove"
type="bool"/>
<preference id="privacy.spoof_english"
name="privacy.spoof_english"
type="int"/>
</preferences>
<script type="application/javascript" src="chrome://browser/content/preferences/languages.js"/>
@ -52,6 +55,11 @@
</stringbundleset>
<description>&languages.customize2.description;</description>
<checkbox id="spoofEnglish"
label="&languages.customize.spoofEnglish;"
preference="privacy.spoof_english"
onsyncfrompreference="return gLanguagesDialog.readSpoofEnglish();"
onsynctopreference="return gLanguagesDialog.writeSpoofEnglish();"/>
<grid flex="1">
<columns>
<column flex="1"/>

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

@ -4,16 +4,16 @@
const TEST_STATE = {
windows: [{
tabs: [
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com" }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
{ entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
]
}]
};
@ -21,7 +21,7 @@ const TEST_STATE = {
const TEST_STATE_2 = {
windows: [{
tabs: [
{ entries: [{ url: "about:robots" }]
{ entries: [{ url: "about:robots", triggeringPrincipal_base64 }]
},
{ entries: [],
userTypedValue: "http://example.com",

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

@ -40,10 +40,10 @@ add_task(async function() {
await promiseBrowserState({
windows: [{
tabs: [
{ entries: [{ url: REMOTE_URL }] },
{ entries: [{ url: ABOUT_ROBOTS_URI }] },
{ entries: [{ url: REMOTE_URL }] },
{ entries: [{ url: NO_TITLE_URL }] },
{ entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] },
{ entries: [{ url: ABOUT_ROBOTS_URI, triggeringPrincipal_base64 }] },
{ entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] },
{ entries: [{ url: NO_TITLE_URL, triggeringPrincipal_base64 }] },
]
}]
});

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

@ -45,8 +45,9 @@ add_UITour_task(async function test_openPrivacyReports() {
let tab = await promiseTabOpened;
await BrowserTestUtils.waitForEvent(gBrowser.selectedBrowser, "Initialized");
let doc = gBrowser.selectedBrowser.contentDocument;
let reports = doc.querySelector("groupbox[data-subcategory='reports']");
is(doc.location.hash, "#privacy", "Should not display the reports subcategory in the location hash.");
is(reports.hidden, false, "Should open to the reports subcategory in the privacy pane in the new Preferences.");
await TestUtils.waitForCondition(() => doc.querySelector(".spotlight"),
"Wait for the reports section is spotlighted.");
is(doc.querySelector(".spotlight").getAttribute("data-subcategory"), "reports", "The reports section is spotlighted.");
await BrowserTestUtils.removeTab(tab);
});

25
browser/extensions/asan-reporter/bootstrap.js поставляемый
Просмотреть файл

@ -31,12 +31,37 @@ logger.addAppender(new Log.ConsoleAppender(new Log.BasicFormatter()));
logger.addAppender(new Log.DumpAppender(new Log.BasicFormatter()));
logger.level = Preferences.get(PREF_LOG_LEVEL, Log.Level.Info);
this.TabCrashObserver = {
init() {
if (this.initialized)
return;
this.initialized = true;
Services.obs.addObserver(this, "ipc:content-shutdown");
},
observe(aSubject, aTopic, aData) {
if (aTopic == "ipc:content-shutdown") {
aSubject.QueryInterface(Ci.nsIPropertyBag2);
if (!aSubject.get("abnormal")) {
return;
}
processDirectory("/tmp");
}
},
};
function install(aData, aReason) {}
function uninstall(aData, aReason) {}
function startup(aData, aReason) {
logger.info("Starting up...");
// Install a handler to observe tab crashes, so we can report those right
// after they happen instead of relying on the user to restart the browser.
TabCrashObserver.init();
// We could use OS.Constants.Path.tmpDir here, but unfortunately there is
// no way in C++ to get the same value *prior* to xpcom initialization.
// Since ASan needs its options, including the "log_path" option already

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

@ -2,7 +2,7 @@
mkdir tmp/
git clone --no-checkout --depth 1 https://github.com/choller/firefox-asan-reporter tmp/
(cd tmp && git reset --hard e1a5d7dc5a2706af72bac0f11eab34b3afdb48ba)
(cd tmp && git reset --hard d508c6e3f5df752a9a7a2d6f1e4e7261ec2290e7)
# Copy only whitelisted files
cp tmp/bootstrap.js tmp/install.rdf.in tmp/moz.build tmp/README.md tmp/LICENSE .

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

@ -416,7 +416,7 @@ var FormAutofillContent = {
}
let records = handler.createRecords();
if (!Object.keys(records).length) {
if (!Object.values(records).some(typeRecords => typeRecords.length)) {
return true;
}

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

@ -986,12 +986,27 @@ class FormAutofillHandler {
}
}
/**
* Collect the filled sections within submitted form and convert all the valid
* field data into multiple records.
*
* @returns {Object} records
* {Array.<Object>} records.address
* {Array.<Object>} records.creditCard
*/
createRecords() {
// TODO [Bug 1415073] `FormAutofillHandler.createRecords` should traverse
// all sections and aggregate the records into one result.
if (this.sections.length > 0) {
return this.sections[0].createRecords();
const records = {
address: [],
creditCard: [],
};
for (const section of this.sections) {
const secRecords = section.createRecords();
for (const [type, record] of Object.entries(secRecords)) {
records[type].push(record);
}
}
return null;
log.debug("Create records:", records);
return records;
}
}

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

@ -21,6 +21,7 @@ FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
const PREF_HEURISTICS_ENABLED = "extensions.formautofill.heuristics.enabled";
const PREF_SECTION_ENABLED = "extensions.formautofill.section.enabled";
const DEFAULT_SECTION_NAME = "-moz-section-default";
/**
* A scanner for traversing all elements in a form and retrieving the field
@ -35,11 +36,13 @@ class FieldScanner {
* @param {Array.DOMElement} elements
* The elements from a form for each parser.
*/
constructor(elements) {
constructor(elements, {allowDuplicates = false, sectionEnabled = true}) {
this._elementsWeakRef = Cu.getWeakReference(elements);
this.fieldDetails = [];
this._parsingIndex = 0;
this._sections = [];
this._allowDuplicates = allowDuplicates;
this._sectionEnabled = sectionEnabled;
}
get _elements() {
@ -112,22 +115,61 @@ class FieldScanner {
});
}
getSectionFieldDetails(allowDuplicates) {
// TODO: [Bug 1416664] If there is only one section which is not defined by
// `autocomplete` attribute, the sections should be classified by the
// heuristics.
return this._sections.map(section => {
if (allowDuplicates) {
return section.fieldDetails;
_classifySections() {
let fieldDetails = this._sections[0].fieldDetails;
this._sections = [];
let seenTypes = new Set();
let previousType;
let sectionCount = 0;
for (let fieldDetail of fieldDetails) {
if (!fieldDetail.fieldName) {
continue;
}
return this._trimFieldDetails(section.fieldDetails);
});
if (seenTypes.has(fieldDetail.fieldName) &&
previousType != fieldDetail.fieldName) {
seenTypes.clear();
sectionCount++;
}
previousType = fieldDetail.fieldName;
seenTypes.add(fieldDetail.fieldName);
this._pushToSection(DEFAULT_SECTION_NAME + "-" + sectionCount, fieldDetail);
}
}
/**
* The result is an array contains the sections with its belonging field
* details. If `this._sections` contains one section only with the default
* section name (DEFAULT_SECTION_NAME), `this._classifySections` should be
* able to identify all sections in the heuristic way.
*
* @returns {Array<Object>}
* The array with the sections, and the belonging fieldDetails are in
* each section.
*/
getSectionFieldDetails() {
// When the section feature is disabled, `getSectionFieldDetails` should
// provide a single section result.
if (!this._sectionEnabled) {
return [this._getFinalDetails(this.fieldDetails)];
}
if (this._sections.length == 0) {
return [];
}
if (this._sections.length == 1 && this._sections[0].name == DEFAULT_SECTION_NAME) {
this._classifySections();
}
return this._sections.map(section =>
this._getFinalDetails(section.fieldDetails)
);
}
/**
* This function will prepare an autocomplete info object with getInfo
* function and push the detail to fieldDetails property. Any duplicated
* detail will be marked as _duplicated = true for the parser.
* function and push the detail to fieldDetails property.
* Any field will be pushed into `this._sections` based on the section name
* in `autocomplete` attribute.
*
* Any element without the related detail will be used for adding the detail
* to the end of field details.
@ -154,13 +196,6 @@ class FieldScanner {
fieldInfo._reason = info._reason;
}
// Store the association between the field metadata and the element.
if (this.findSameField(info) != -1) {
// A field with the same identifier already exists.
log.debug("Not collecting a field matching another with the same info:", info);
fieldInfo._duplicated = true;
}
this.fieldDetails.push(fieldInfo);
this._pushToSection(this._getSectionName(fieldInfo), fieldInfo);
}
@ -173,7 +208,7 @@ class FieldScanner {
if (info.addressType) {
names.push(info.addressType);
}
return names.length ? names.join(" ") : "-moz-section-default";
return names.length ? names.join(" ") : DEFAULT_SECTION_NAME;
}
/**
@ -190,22 +225,19 @@ class FieldScanner {
throw new Error("Try to update the non-existing field detail.");
}
this.fieldDetails[index].fieldName = fieldName;
delete this.fieldDetails[index]._duplicated;
let indexSame = this.findSameField(this.fieldDetails[index]);
if (indexSame != index && indexSame != -1) {
this.fieldDetails[index]._duplicated = true;
}
}
findSameField(info) {
return this.fieldDetails.findIndex(f => f.section == info.section &&
f.addressType == info.addressType &&
f.fieldName == info.fieldName);
_isSameField(field1, field2) {
return field1.section == field2.section &&
field1.addressType == field2.addressType &&
field1.fieldName == field2.fieldName;
}
/**
* Provide the field details without invalid field name and duplicated fields.
* Provide the final field details without invalid field name, and the
* duplicated fields will be removed as well. For the debugging purpose,
* the final `fieldDetails` will include the duplicated fields if
* `_allowDuplicates` is true.
*
* @param {Array<Object>} fieldDetails
* The field details for trimming.
@ -213,12 +245,20 @@ class FieldScanner {
* The array with the field details without invalid field name and
* duplicated fields.
*/
_trimFieldDetails(fieldDetails) {
return fieldDetails.filter(f => f.fieldName && !f._duplicated);
}
_getFinalDetails(fieldDetails) {
if (this._allowDuplicates) {
return fieldDetails.filter(f => f.fieldName);
}
getFieldDetails(allowDuplicates) {
return allowDuplicates ? this.fieldDetails : this._trimFieldDetails(this.fieldDetails);
let dedupedFieldDetails = [];
for (let fieldDetail of fieldDetails) {
if (fieldDetail.fieldName && !dedupedFieldDetails.find(f => this._isSameField(fieldDetail, f))) {
dedupedFieldDetails.push(fieldDetail);
} else {
log.debug("Not collecting an invalid field or matching another with the same info:", fieldDetail);
}
}
return dedupedFieldDetails;
}
elementExisting(index) {
@ -651,7 +691,8 @@ this.FormAutofillHeuristics = {
return [];
}
let fieldScanner = new FieldScanner(eligibleFields);
let fieldScanner = new FieldScanner(eligibleFields,
{allowDuplicates, sectionEnabled: this._sectionEnabled});
while (!fieldScanner.parsingFinished) {
let parsedPhoneFields = this._parsePhoneFields(fieldScanner);
let parsedAddressFields = this._parseAddressFields(fieldScanner);
@ -666,13 +707,7 @@ this.FormAutofillHeuristics = {
LabelUtils.clearLabelMap();
if (!this._sectionEnabled) {
// When the section feature is disabled, `getFormInfo` should provide a
// single section result.
return [fieldScanner.getFieldDetails(allowDuplicates)];
}
return fieldScanner.getSectionFieldDetails(allowDuplicates);
return fieldScanner.getSectionFieldDetails();
},
_regExpTableHashValue(...signBits) {

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

@ -27,7 +27,9 @@
"use strict";
this.EXPORTED_SYMBOLS = ["FormAutofillParent"];
// We expose a singleton from this module. Some tests may import the
// constructor via a backstage pass.
this.EXPORTED_SYMBOLS = ["formAutofillParent"];
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
@ -78,10 +80,30 @@ FormAutofillParent.prototype = {
*/
_active: null,
/**
* The status of Form Autofill's initialization.
*/
_initialized: false,
/**
* Exposes the status of Form Autofill's initialization. It can be used to
* determine whether Form Autofill is available for current users.
*
* @returns {boolean} Whether FormAutofillParent is initialized.
*/
get initialized() {
return this._initialized;
},
/**
* Initializes ProfileStorage and registers the message handler.
*/
async init() {
if (this._initialized) {
return;
}
this._initialized = true;
Services.obs.addObserver(this, "sync-pane-loaded");
Services.ppmm.addMessageListener("FormAutofill:InitStorage", this);
Services.ppmm.addMessageListener("FormAutofill:GetRecords", this);
@ -361,6 +383,7 @@ FormAutofillParent.prototype = {
},
_onAddressSubmit(address, target, timeStartedFillingMS) {
let showDoorhanger = null;
if (address.guid) {
// Avoid updating the fields that users don't modify.
let originalAddress = this.profileStorage.addresses.get(address.guid);
@ -373,7 +396,8 @@ FormAutofillParent.prototype = {
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record, true)) {
this._recordFormFillingTime("address", "autofill-update", timeStartedFillingMS);
FormAutofillDoorhanger.show(target, "updateAddress").then((state) => {
showDoorhanger = async () => {
const state = await FormAutofillDoorhanger.show(target, "updateAddress");
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record, true);
switch (state) {
case "create":
@ -391,15 +415,15 @@ FormAutofillParent.prototype = {
break;
}
changedGUIDs.forEach(guid => this.profileStorage.addresses.notifyUsed(guid));
});
};
// Address should be updated
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill_update", 1);
return;
} else {
this._recordFormFillingTime("address", "autofill", timeStartedFillingMS);
this.profileStorage.addresses.notifyUsed(address.guid);
// Address is merged successfully
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill", 1);
}
this._recordFormFillingTime("address", "autofill", timeStartedFillingMS);
this.profileStorage.addresses.notifyUsed(address.guid);
// Address is merged successfully
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill", 1);
} else {
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record);
if (!changedGUIDs.length) {
@ -411,22 +435,24 @@ FormAutofillParent.prototype = {
// Show first time use doorhanger
if (FormAutofillUtils.isAutofillAddressesFirstTimeUse) {
Services.prefs.setBoolPref(FormAutofillUtils.ADDRESSES_FIRST_TIME_USE_PREF, false);
FormAutofillDoorhanger.show(target, "firstTimeUse").then((state) => {
showDoorhanger = async () => {
const state = await FormAutofillDoorhanger.show(target, "firstTimeUse");
if (state !== "open-pref") {
return;
}
target.ownerGlobal.openPreferences("panePrivacy",
{origin: "autofillDoorhanger"});
});
};
} else {
// We want to exclude the first time form filling.
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_manual", 1);
}
}
return showDoorhanger;
},
async _onCreditCardSubmit(creditCard, target, timeStartedFillingMS) {
_onCreditCardSubmit(creditCard, target, timeStartedFillingMS) {
// Updates the used status for shield/heartbeat to recognize users who have
// used Credit Card Autofill.
let setUsedStatus = status => {
@ -463,7 +489,7 @@ FormAutofillParent.prototype = {
// Add probe to record credit card autofill(without modification).
Services.telemetry.scalarAdd("formautofill.creditCards.fill_type_autofill", 1);
this._recordFormFillingTime("creditCard", "autofill", timeStartedFillingMS);
return;
return false;
}
// Add the probe to record credit card autofill with modification.
Services.telemetry.scalarAdd("formautofill.creditCards.fill_type_autofill_modified", 1);
@ -483,55 +509,79 @@ FormAutofillParent.prototype = {
let dupGuid = this.profileStorage.creditCards.getDuplicateGuid(creditCard.record);
if (dupGuid) {
this.profileStorage.creditCards.notifyUsed(dupGuid);
return;
return false;
}
// Indicate that the user has seen the doorhanger.
setUsedStatus(2);
let state = await FormAutofillDoorhanger.show(target, creditCard.guid ? "updateCreditCard" : "addCreditCard");
if (state == "cancel") {
return;
}
if (state == "disable") {
Services.prefs.setBoolPref("extensions.formautofill.creditCards.enabled", false);
return;
}
// TODO: "MasterPassword.ensureLoggedIn" can be removed after the storage
// APIs are refactored to be async functions (bug 1399367).
if (!await MasterPassword.ensureLoggedIn()) {
log.warn("User canceled master password entry");
return;
}
let changedGUIDs = [];
if (creditCard.guid) {
if (state == "update") {
this.profileStorage.creditCards.update(creditCard.guid, creditCard.record, true);
changedGUIDs.push(creditCard.guid);
} else if ("create") {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
return async () => {
// Suppress the pending doorhanger from showing up if user disabled credit card in previous doorhanger.
if (!FormAutofillUtils.isAutofillCreditCardsEnabled) {
return;
}
} else {
changedGUIDs.push(...this.profileStorage.creditCards.mergeToStorage(creditCard.record));
if (!changedGUIDs.length) {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
const state = await FormAutofillDoorhanger.show(target, creditCard.guid ? "updateCreditCard" : "addCreditCard");
if (state == "cancel") {
return;
}
}
changedGUIDs.forEach(guid => this.profileStorage.creditCards.notifyUsed(guid));
if (state == "disable") {
Services.prefs.setBoolPref("extensions.formautofill.creditCards.enabled", false);
return;
}
// TODO: "MasterPassword.ensureLoggedIn" can be removed after the storage
// APIs are refactored to be async functions (bug 1399367).
if (!await MasterPassword.ensureLoggedIn()) {
log.warn("User canceled master password entry");
return;
}
let changedGUIDs = [];
if (creditCard.guid) {
if (state == "update") {
this.profileStorage.creditCards.update(creditCard.guid, creditCard.record, true);
changedGUIDs.push(creditCard.guid);
} else if ("create") {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
}
} else {
changedGUIDs.push(...this.profileStorage.creditCards.mergeToStorage(creditCard.record));
if (!changedGUIDs.length) {
changedGUIDs.push(this.profileStorage.creditCards.add(creditCard.record));
}
}
changedGUIDs.forEach(guid => this.profileStorage.creditCards.notifyUsed(guid));
};
},
_onFormSubmit(data, target) {
async _onFormSubmit(data, target) {
let {profile: {address, creditCard}, timeStartedFillingMS} = data;
if (address) {
this._onAddressSubmit(address, target, timeStartedFillingMS);
}
if (creditCard) {
this._onCreditCardSubmit(creditCard, target, timeStartedFillingMS);
// Don't record filling time if any type of records has more than one section being
// populated. We've been recording the filling time, so the other cases that aren't
// recorded on the same basis should be out of the data samples. E.g. Filling time of
// populating one profile is different from populating two sections, therefore, we
// shouldn't record the later to regress the representation of existing statistics.
if (address.length > 1 || creditCard.length > 1) {
timeStartedFillingMS = null;
}
// Transmit the telemetry immediately in the meantime form submitted, and handle these pending
// doorhangers at a later.
await Promise.all([
address.map(addrRecord => this._onAddressSubmit(addrRecord, target, timeStartedFillingMS)),
creditCard.map(ccRecord => this._onCreditCardSubmit(ccRecord, target, timeStartedFillingMS)),
].map(pendingDoorhangers => {
return pendingDoorhangers.filter(pendingDoorhanger => !!pendingDoorhanger &&
typeof pendingDoorhanger == "function");
}).map(pendingDoorhangers => new Promise(async resolve => {
for (const showDoorhanger of pendingDoorhangers) {
await showDoorhanger();
}
resolve();
})));
},
/**
* Set the probes for the filling time with specific filling type and form type.
@ -552,3 +602,5 @@ FormAutofillParent.prototype = {
histogram.add(`${formType}-${fillingType}`, Date.now() - startedFillingMS);
},
};
this.formAutofillParent = new FormAutofillParent();

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

@ -87,6 +87,7 @@ FormAutofillPreferences.prototype = {
addressAutofill.id = "addressAutofill";
addressAutofillLearnMore.id = "addressAutofillLearnMore";
addressAutofill.setAttribute("data-subcategory", "address-autofill");
addressAutofillLearnMore.setAttribute("value", this.bundle.GetStringFromName("learnMoreLabel"));
addressAutofillCheckbox.setAttribute("label", this.bundle.GetStringFromName("autofillAddressesCheckbox"));
savedAddressesBtn.setAttribute("label", this.bundle.GetStringFromName("savedAddressesBtnLabel"));
@ -130,6 +131,7 @@ FormAutofillPreferences.prototype = {
creditCardAutofill.id = "creditCardAutofill";
creditCardAutofillLearnMore.id = "creditCardAutofillLearnMore";
creditCardAutofill.setAttribute("data-subcategory", "credit-card-autofill");
creditCardAutofillLearnMore.setAttribute("value", this.bundle.GetStringFromName("learnMoreLabel"));
creditCardAutofillCheckbox.setAttribute("label", this.bundle.GetStringFromName("autofillCreditCardsCheckbox"));
savedCreditCardsBtn.setAttribute("label", this.bundle.GetStringFromName("savedCreditCardsBtnLabel"));

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

@ -16,7 +16,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManagerPrivate",
"resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillParent",
XPCOMUtils.defineLazyModuleGetter(this, "formAutofillParent",
"resource://formautofill/FormAutofillParent.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "FormAutofillUtils",
"resource://formautofill/FormAutofillUtils.jsm");
@ -110,8 +110,7 @@ function startup(data) {
// Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
let parent = new FormAutofillParent();
parent.init().catch(Cu.reportError);
formAutofillParent.init().catch(Cu.reportError);
Services.ppmm.loadProcessScript("data:,new " + function() {
Components.utils.import("resource://formautofill/FormAutofillContent.jsm");
}, true);

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

@ -2,10 +2,20 @@
* 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/. */
html {
/* Prevent unnecessary horizontal scroll bar from showing */
overflow-x: hidden;
}
div {
display: flex;
}
button {
padding-right: 10px;
padding-left: 10px;
}
fieldset {
margin: 0;
padding: 0;

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

@ -49,7 +49,7 @@ class ManageRecords {
}
localizeDocument() {
document.documentElement.style.width = FormAutofillUtils.stringBundle.GetStringFromName("manageDialogsWidth");
document.documentElement.style.minWidth = FormAutofillUtils.stringBundle.GetStringFromName("manageDialogsWidth");
FormAutofillUtils.localizeMarkup(AUTOFILL_BUNDLE_URI, document);
}

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

@ -37,6 +37,11 @@ textarea {
resize: none;
}
button {
padding-right: 10px;
padding-left: 10px;
}
input,
select {
box-sizing: border-box;

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

@ -11,32 +11,69 @@
<label>Organization: <input id="organization" autocomplete="organization"></label><br/>
<br/>
<label>Street Address: <input id="street-address" autocomplete="shipping street-address"></label><br/>
<label>Address Level 2: <input id="address-level2" autocomplete="shipping address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1" autocomplete="shipping address-level1"></label><br/>
<label>Postal Code: <input id="postal-code" autocomplete="shipping postal-code"></label><br/>
<label>Country: <input id="country" autocomplete="shipping country"></label><br/>
<label>Street Address: <input id="street-address-a" autocomplete="shipping street-address"></label><br/>
<label>Address Level 2: <input id="address-level2-a" autocomplete="shipping address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1-a" autocomplete="shipping address-level1"></label><br/>
<label>Postal Code: <input id="postal-code-a" autocomplete="shipping postal-code"></label><br/>
<label>Country: <input id="country-a" autocomplete="shipping country"></label><br/>
<br/>
<label>Street Address: <input id="street-address" autocomplete="billing street-address"></label><br/>
<label>Address Level 2: <input id="address-level2" autocomplete="billing address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1" autocomplete="billing address-level1"></label><br/>
<label>Postal Code: <input id="postal-code" autocomplete="billing postal-code"></label><br/>
<label>Country: <input id="country" autocomplete="billing country"></label><br/>
<label>Street Address: <input id="street-address-b" autocomplete="billing street-address"></label><br/>
<label>Address Level 2: <input id="address-level2-b" autocomplete="billing address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1-b" autocomplete="billing address-level1"></label><br/>
<label>Postal Code: <input id="postal-code-b" autocomplete="billing postal-code"></label><br/>
<label>Country: <input id="country-b" autocomplete="billing country"></label><br/>
<br/>
<label>Street Address: <input id="street-address" autocomplete="section-my street-address"></label><br/>
<label>Address Level 2: <input id="address-level2" autocomplete="section-my address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1" autocomplete="section-my address-level1"></label><br/>
<label>Postal Code: <input id="postal-code" autocomplete="section-my postal-code"></label><br/>
<label>Country: <input id="country" autocomplete="section-my country"></label><br/>
<label>Street Address: <input id="street-address-c" autocomplete="section-my street-address"></label><br/>
<label>Address Level 2: <input id="address-level2-c" autocomplete="section-my address-level2"></label><br/>
<label>Address Level 1: <input id="address-level1-c" autocomplete="section-my address-level1"></label><br/>
<label>Postal Code: <input id="postal-code-c" autocomplete="section-my postal-code"></label><br/>
<label>Country: <input id="country-c" autocomplete="section-my country"></label><br/>
<br/>
<label>Telephone: <input id="tel" autocomplete="work tel"></label><br/>
<label>Email: <input id="email" autocomplete="work email"></label><br/>
<label>Telephone: <input id="tel-a" autocomplete="work tel"></label><br/>
<label>Email: <input id="email-a" autocomplete="work email"></label><br/>
<br/>
<label>Telephone: <input id="tel" autocomplete="home tel"></label><br/>
<label>Email: <input id="email" autocomplete="home email"></label><br/>
<label>Telephone: <input id="tel-b" autocomplete="home tel"></label><br/>
<label>Email: <input id="email-b" autocomplete="home email"></label><br/>
<p>
<input type="submit" value="Submit">
<button type="reset">Reset</button>
</p>
</form>
<form>
<label>Name: <input autocomplete="name"></label><br/>
<label>Organization: <input autocomplete="organization"></label><br/>
<br/>
<label>Street Address: <input autocomplete="street-address"></label><br/>
<label>Address Level 2: <input autocomplete="address-level2"></label><br/>
<label>Address Level 1: <input autocomplete="address-level1"></label><br/>
<label>Postal Code: <input autocomplete="postal-code"></label><br/>
<label>Country: <input autocomplete="country"></label><br/>
<br/>
<label>Street Address: <input autocomplete="street-address"></label><br/>
<label>Address Level 2: <input autocomplete="address-level2"></label><br/>
<label>Address Level 1: <input autocomplete="address-level1"></label><br/>
<label>Postal Code: <input autocomplete="postal-code"></label><br/>
<label>Country: <input autocomplete="country"></label><br/>
<br/>
<label>Street Address: <input autocomplete="street-address"></label><br/>
<label>Address Level 2: <input autocomplete="address-level2"></label><br/>
<label>Address Level 1: <input autocomplete="address-level1"></label><br/>
<label>Postal Code: <input autocomplete="postal-code"></label><br/>
<label>Country: <input autocomplete="country"></label><br/>
<br/>
<label>Telephone: <input autocomplete="work tel"></label><br/>
<label>Email: <input autocomplete="work email"></label><br/>
<br/>
<label>Telephone: <input autocomplete="home tel"></label><br/>
<label>Email: <input autocomplete="home email"></label><br/>
<p>
<input type="submit" value="Submit">
<button type="reset">Reset</button>

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

@ -41,6 +41,37 @@ runHeuristicsTest([
{"section": "section-my", "addressType": "", "contactType": "", "fieldName": "country"},
],
],
[
[
{"section": "", "addressType": "", "contactType": "", "fieldName": "name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "organization"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
],
[
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
],
[
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level1"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
{"section": "", "addressType": "", "contactType": "work", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "work", "fieldName": "email"},
],
[
{"section": "", "addressType": "", "contactType": "home", "fieldName": "tel"},
{"section": "", "addressType": "", "contactType": "home", "fieldName": "email"},
],
],
],
},
], "../../fixtures/");

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

@ -6,7 +6,7 @@ runHeuristicsTest([
{
fixturePath: "Checkout_ShippingAddress.html",
expectedResult: [
[[]], // Search form
[], // Search form
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
@ -26,7 +26,7 @@ runHeuristicsTest([
}, {
fixturePath: "Checkout_Payment.html",
expectedResult: [
[[]], // Search form
[], // Search form
[[ // Sign up
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],

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

@ -20,9 +20,10 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
], [
// The below "tel-extension" is correct and removed due to the
// duplicated field above.
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
]],
[],
],
@ -47,6 +48,8 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
]],
[],
],
@ -54,7 +57,7 @@ runHeuristicsTest([
fixturePath: "Checkout_Logon.html",
expectedResult: [
[],
[[]],
[],
[],
],
},

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

@ -50,7 +50,6 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"}, // ac-off
]],
@ -58,7 +57,7 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
]],
[],
[[]],
[],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "additional-name"}, // middle-name initial
@ -96,7 +95,7 @@ runHeuristicsTest([
}, {
fixturePath: "SignIn.html",
expectedResult: [
[[]],
[],
[],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},

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

@ -16,10 +16,7 @@ runHeuristicsTest([
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
]],
[
/*
*/
],
[],
],
}, {
fixturePath: "Checkout_Payment.html",
@ -56,7 +53,7 @@ runHeuristicsTest([
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
[[]],
[],
[],
[],
],

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

@ -26,6 +26,9 @@ runHeuristicsTest([
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-month"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp-year"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},

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

@ -55,9 +55,9 @@ runHeuristicsTest([
}, {
fixturePath: "SignIn.html",
expectedResult: [
[[ // ac-off
[ // ac-off
// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
],
],
},
], "../../../fixtures/third_party/OfficeDepot/");

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

@ -13,11 +13,11 @@ runHeuristicsTest([
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
@ -33,11 +33,11 @@ runHeuristicsTest([
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-day"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "bday-year"}, // select
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-type"}, // select
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-exp"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "cc-csc"},
], [
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"}, // ac-off
]],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
@ -46,7 +46,7 @@ runHeuristicsTest([
}, {
fixturePath: "SignIn.html",
expectedResult: [
[[]],
[],
[[ // Sign in
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],

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

@ -7,11 +7,11 @@ runHeuristicsTest([
fixturePath: "ShippingAddress.html",
expectedResult: [
[],
[[]], // search form, ac-off
[[ // ac-off
[], // search form, ac-off
[ // ac-off
// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
[[ // check-out, ac-off
],
[ // check-out, ac-off
/*
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
@ -24,7 +24,7 @@ runHeuristicsTest([
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
*/
]],
],
[ // ac-off
/*
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
@ -40,18 +40,18 @@ runHeuristicsTest([
// {"section": "", "addressType": "", "contactType": "", "fieldName": "new-password"},
*/
],
[[ // ac-off
[ // ac-off
// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
[[ // ac-off
],
[ // ac-off
// {"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
]],
],
],
}, {
fixturePath: "PaymentOptions.html",
expectedResult: [
[],
[[]], // search
[], // search
[[ // credit card
{"section": "", "addressType": "", "contactType": "", "fieldName": "cc-number"},
// FIXME: bug 1392958 - Cardholder name field should be detected as cc-name

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

@ -6,7 +6,7 @@ runHeuristicsTest([
{
fixturePath: "Basic.html",
expectedResult: [
[[ // ac-off
[ // ac-off
// {"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "address-line1"},
@ -14,7 +14,7 @@ runHeuristicsTest([
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "organization"},
]],
],
],
}, {
fixturePath: "Basic_ac_on.html",

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

@ -9,7 +9,7 @@ runHeuristicsTest([
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
]],
[[]],
[],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
// {"section": "", "addressType": "", "contactType": "", "fieldName": "password"}, // ac-off
@ -25,7 +25,7 @@ runHeuristicsTest([
}, {
fixturePath: "Payment.html",
expectedResult: [
[[]],
[],
[
[
{"section": "section-payment", "addressType": "", "contactType": "", "fieldName": "given-name"},
@ -50,7 +50,7 @@ runHeuristicsTest([
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "postal-code"},
]],
[[]],
[],
[[
{"section": "", "addressType": "", "contactType": "", "fieldName": "given-name"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "family-name"},

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

@ -4,7 +4,7 @@
"use strict";
Cu.import("resource://formautofill/FormAutofillParent.jsm");
let {FormAutofillParent} = Cu.import("resource://formautofill/FormAutofillParent.jsm", {});
Cu.import("resource://formautofill/ProfileStorage.jsm");
add_task(async function test_activeStatus_init() {

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

@ -292,10 +292,22 @@ const TESTCASES = [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-extension"},
],
creditCardFieldDetails: [],
}, {
addressFieldDetails: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
// TODO Bug 1421181 - "tel-country-code" field should belong to the next
// section. There should be a way to group the related fields during the
// parsing stage.
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-country-code"},
],
creditCardFieldDetails: [],
}, {
addressFieldDetails: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-area-code"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-prefix"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel-local-suffix"},
@ -461,13 +473,10 @@ for (let tc of TESTCASES) {
Assert.equal(detail.elementWeakRef.get(), testCaseDetails[index].elementWeakRef.get(), "DOM reference");
});
}
for (let i = 0; i < testcase.sections.length; i++) {
let section = testcase.sections[i];
[
section.addressFieldDetails,
section.creditCardFieldDetails,
].forEach(details => setElementWeakRef(details));
}
setElementWeakRef(testcase.sections.reduce((fieldDetails, section) => {
fieldDetails.push(...section.addressFieldDetails, ...section.creditCardFieldDetails);
return fieldDetails;
}, []));
setElementWeakRef(testcase.validFieldDetails);
let handler = new FormAutofillHandler(formLike);

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

@ -26,16 +26,16 @@ const TESTCASES = [
"cc-name": "*".repeat(201),
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "*".repeat(200),
"address-level1": "",
"country": "US",
},
creditCard: {
}],
creditCard: [{
"cc-number": "1111222233334444",
"cc-name": "",
},
}],
},
},
{
@ -50,7 +50,8 @@ const TESTCASES = [
"organization": "Mozilla",
},
expectedRecord: {
address: undefined,
address: [],
creditCard: [],
},
},
{
@ -66,11 +67,12 @@ const TESTCASES = [
"country": "United States",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"country": "United States",
},
}],
creditCard: [],
},
},
{
@ -86,11 +88,12 @@ const TESTCASES = [
"country": "United States",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"country": "US",
},
}],
creditCard: [],
},
},
{
@ -108,11 +111,12 @@ const TESTCASES = [
"tel-national": "1234567890",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"tel": "+11234567890",
},
}],
creditCard: [],
},
},
{
@ -130,12 +134,13 @@ const TESTCASES = [
"tel": "1234",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"country": "United States",
"tel": "",
},
}],
creditCard: [],
},
},
{
@ -153,12 +158,13 @@ const TESTCASES = [
"tel": "1234567890123456",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"country": "United States",
"tel": "",
},
}],
creditCard: [],
},
},
{
@ -176,12 +182,13 @@ const TESTCASES = [
"tel": "12345###!!!",
},
expectedRecord: {
address: {
address: [{
"given-name": "John",
"organization": "Mozilla",
"country": "United States",
"tel": "",
},
}],
creditCard: [],
},
},
{
@ -197,7 +204,8 @@ const TESTCASES = [
"organization": "Mozilla",
},
expectedRecord: {
address: undefined,
address: [],
creditCard: [],
},
},
{
@ -215,7 +223,8 @@ const TESTCASES = [
"organization": "Mozilla",
},
expectedRecord: {
address: undefined,
address: [],
creditCard: [],
},
},
{
@ -231,11 +240,12 @@ const TESTCASES = [
"cc-exp": "2022-06",
},
expectedRecord: {
creditCard: {
address: [],
creditCard: [{
"cc-number": "4444000022220000",
"cc-name": "Foo Bar",
"cc-exp": "2022-06",
},
}],
},
},
{
@ -247,9 +257,10 @@ const TESTCASES = [
"cc-number": "4444000022220000",
},
expectedRecord: {
creditCard: {
address: [],
creditCard: [{
"cc-number": "4444000022220000",
},
}],
},
},
{
@ -265,7 +276,8 @@ const TESTCASES = [
"cc-exp": "2022-06",
},
expectedRecord: {
creditCard: undefined,
address: [],
creditCard: [],
},
},
{
@ -279,9 +291,80 @@ const TESTCASES = [
"cc-exp": "2022-06",
},
expectedRecord: {
creditCard: undefined,
address: [],
creditCard: [],
},
},
{
description: "A form with multiple sections",
document: `<form>
<input id="given-name" autocomplete="given-name">
<input id="organization" autocomplete="organization">
<input id="country" autocomplete="country">
<input id="given-name-shipping" autocomplete="shipping given-name">
<input id="family-name-shipping" autocomplete="shipping family-name">
<input id="organization-shipping" autocomplete="shipping organization">
<input id="country-shipping" autocomplete="shipping country">
<input id="given-name-billing" autocomplete="billing given-name">
<input id="organization-billing" autocomplete="billing organization">
<input id="country-billing" autocomplete="billing country">
<input id="cc-number-section-one" autocomplete="section-one cc-number">
<input id="cc-name-section-one" autocomplete="section-one cc-name">
<input id="cc-number-section-two" autocomplete="section-two cc-number">
<input id="cc-name-section-two" autocomplete="section-two cc-name">
<input id="cc-exp-section-two" autocomplete="section-two cc-exp">
</form>`,
formValue: {
"given-name": "Bar",
"organization": "Foo",
"country": "US",
"given-name-shipping": "John",
"family-name-shipping": "Doe",
"organization-shipping": "Mozilla",
"country-shipping": "US",
"given-name-billing": "Foo",
"organization-billing": "Bar",
"country-billing": "US",
"cc-number-section-one": "4444000022220000",
"cc-name-section-one": "John",
"cc-number-section-two": "4444000022221111",
"cc-name-section-two": "Foo Bar",
"cc-exp-section-two": "2026-26",
},
expectedRecord: {
address: [{
"given-name": "Bar",
"organization": "Foo",
"country": "US",
}, {
"given-name": "John",
"family-name": "Doe",
"organization": "Mozilla",
"country": "US",
}, {
"given-name": "Foo",
"organization": "Bar",
"country": "US",
}],
creditCard: [{
"cc-number": "4444000022220000",
"cc-name": "John",
}, {
"cc-number": "4444000022221111",
"cc-name": "Foo Bar",
"cc-exp": "2026-26",
}],
},
},
];
for (let testcase of TESTCASES) {
@ -301,12 +384,9 @@ for (let testcase of TESTCASES) {
let record = handler.createRecords();
for (let type in testcase.expectedRecord) {
if (!testcase.expectedRecord[type]) {
do_check_eq(record[type], undefined);
} else {
Assert.deepEqual(record[type].record, testcase.expectedRecord[type]);
}
let expectedRecord = testcase.expectedRecord;
for (let type in record) {
Assert.deepEqual(record[type].map(secRecord => secRecord.record), expectedRecord[type]);
}
});
}

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

@ -4,7 +4,7 @@
"use strict";
Cu.import("resource://formautofill/FormAutofillParent.jsm");
let {FormAutofillParent} = Cu.import("resource://formautofill/FormAutofillParent.jsm", {});
Cu.import("resource://formautofill/MasterPassword.jsm");
Cu.import("resource://formautofill/ProfileStorage.jsm");

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

@ -62,7 +62,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -73,7 +73,8 @@ const TESTCASES = [
"tel": "1-650-903-0800",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -88,7 +89,8 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
creditCard: {
address: [],
creditCard: [{
guid: null,
record: {
"cc-name": "John Doe",
@ -97,7 +99,7 @@ const TESTCASES = [
"cc-exp-year": 2000,
},
untouchedFields: [],
},
}],
},
},
},
@ -115,7 +117,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -126,8 +128,8 @@ const TESTCASES = [
"tel": "1-650-903-0800",
},
untouchedFields: [],
},
creditCard: {
}],
creditCard: [{
guid: null,
record: {
"cc-name": "John Doe",
@ -136,7 +138,7 @@ const TESTCASES = [
"cc-exp-year": 2000,
},
untouchedFields: [],
},
}],
},
},
},
@ -150,7 +152,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -161,7 +163,8 @@ const TESTCASES = [
"tel": "1-650-903-0800",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -176,7 +179,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -187,7 +190,8 @@ const TESTCASES = [
"tel": "1-650-903-0800",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -201,7 +205,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "CA",
@ -212,7 +216,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -226,7 +231,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "CA",
@ -237,7 +242,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -251,7 +257,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "AR",
@ -262,7 +268,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -276,7 +283,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "CA",
@ -287,7 +294,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -301,7 +309,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "AZ",
@ -312,7 +320,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -326,7 +335,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"address-level1": "Arizonac",
@ -337,7 +346,8 @@ const TESTCASES = [
"tel": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -352,7 +362,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -363,7 +373,8 @@ const TESTCASES = [
"email": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -378,7 +389,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -389,7 +400,8 @@ const TESTCASES = [
"email": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -404,7 +416,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -415,7 +427,8 @@ const TESTCASES = [
"email": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -430,7 +443,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -441,7 +454,8 @@ const TESTCASES = [
"email": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -456,7 +470,7 @@ const TESTCASES = [
expectedResult: {
formSubmission: true,
records: {
address: {
address: [{
guid: null,
record: {
"street-address": "331 E. Evelyn Avenue",
@ -467,7 +481,8 @@ const TESTCASES = [
"email": "",
},
untouchedFields: [],
},
}],
creditCard: [],
},
},
},
@ -478,8 +493,8 @@ add_task(async function handle_earlyformsubmit_event() {
let fakeForm = MOCK_DOC.createElement("form");
sinon.spy(FormAutofillContent, "_onFormSubmit");
do_check_eq(FormAutofillContent.notify(fakeForm), true);
do_check_eq(FormAutofillContent._onFormSubmit.called, false);
Assert.equal(FormAutofillContent.notify(fakeForm), true);
Assert.equal(FormAutofillContent._onFormSubmit.called, false);
FormAutofillContent._onFormSubmit.restore();
});
@ -508,33 +523,33 @@ add_task(async function autofill_disabled() {
Services.prefs.setBoolPref("extensions.formautofill.addresses.enabled", false);
Services.prefs.setBoolPref("extensions.formautofill.creditCards.enabled", false);
FormAutofillContent.notify(form);
do_check_eq(FormAutofillContent._onFormSubmit.called, false);
Assert.equal(FormAutofillContent._onFormSubmit.called, false);
FormAutofillContent._onFormSubmit.reset();
// "_onFormSubmit" should be called as usual.
Services.prefs.clearUserPref("extensions.formautofill.addresses.enabled");
Services.prefs.clearUserPref("extensions.formautofill.creditCards.enabled");
FormAutofillContent.notify(form);
do_check_eq(FormAutofillContent._onFormSubmit.called, true);
do_check_neq(FormAutofillContent._onFormSubmit.args[0][0].address, undefined);
do_check_neq(FormAutofillContent._onFormSubmit.args[0][0].creditCard, undefined);
Assert.equal(FormAutofillContent._onFormSubmit.called, true);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].creditCard, []);
FormAutofillContent._onFormSubmit.reset();
// "address" should be empty if "addresses" pref is disabled.
Services.prefs.setBoolPref("extensions.formautofill.addresses.enabled", false);
FormAutofillContent.notify(form);
do_check_eq(FormAutofillContent._onFormSubmit.called, true);
do_check_eq(FormAutofillContent._onFormSubmit.args[0][0].address, undefined);
do_check_neq(FormAutofillContent._onFormSubmit.args[0][0].creditCard, undefined);
Assert.equal(FormAutofillContent._onFormSubmit.called, true);
Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].creditCard, []);
FormAutofillContent._onFormSubmit.reset();
Services.prefs.clearUserPref("extensions.formautofill.addresses.enabled");
// "creditCard" should be empty if "creditCards" pref is disabled.
Services.prefs.setBoolPref("extensions.formautofill.creditCards.enabled", false);
FormAutofillContent.notify(form);
do_check_eq(FormAutofillContent._onFormSubmit.called, true);
do_check_neq(FormAutofillContent._onFormSubmit.args[0][0].address, undefined);
do_check_eq(FormAutofillContent._onFormSubmit.args[0][0].creditCard, undefined);
Assert.deepEqual(FormAutofillContent._onFormSubmit.called, true);
Assert.notDeepEqual(FormAutofillContent._onFormSubmit.args[0][0].address, []);
Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0].creditCard, []);
FormAutofillContent._onFormSubmit.reset();
Services.prefs.clearUserPref("extensions.formautofill.creditCards.enabled");
@ -566,7 +581,7 @@ TESTCASES.forEach(testcase => {
FormAutofillContent.identifyAutofillFields(element);
FormAutofillContent.notify(form);
do_check_eq(FormAutofillContent._onFormSubmit.called,
Assert.equal(FormAutofillContent._onFormSubmit.called,
testcase.expectedResult.formSubmission);
if (FormAutofillContent._onFormSubmit.called) {
Assert.deepEqual(FormAutofillContent._onFormSubmit.args[0][0],

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

@ -4,7 +4,7 @@
"use strict";
Cu.import("resource://formautofill/FormAutofillParent.jsm");
let {FormAutofillParent} = Cu.import("resource://formautofill/FormAutofillParent.jsm", {});
Cu.import("resource://formautofill/ProfileStorage.jsm");
add_task(async function test_profileSavedFieldNames_init() {

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

@ -110,19 +110,19 @@ include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
ifeq (bundle, $(MOZ_FS_LAYOUT))
BINPATH = $(_BINPATH)
DEFINES += -DAPPNAME=$(_APPNAME)
DEFINES += -DAPPNAME='$(_APPNAME)'
else
# Every other platform just winds up in dist/bin
BINPATH = bin
endif
DEFINES += -DBINPATH=$(BINPATH)
DEFINES += -DBINPATH='$(BINPATH)'
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
RESPATH = $(_APPNAME)/Contents/Resources
else
RESPATH = $(BINPATH)
endif
DEFINES += -DRESPATH=$(RESPATH)
DEFINES += -DRESPATH="$(RESPATH)"
LPROJ_ROOT = $(firstword $(subst -, ,$(AB_CD)))
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))

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

@ -171,10 +171,10 @@ endif
ident:
@printf 'fx_revision '
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
$(STAGEDIST)/application.ini App SourceStamp
'$(STAGEDIST)'/application.ini App SourceStamp
@printf 'buildid '
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
$(STAGEDIST)/application.ini App BuildID
'$(STAGEDIST)'/application.ini App BuildID
# test target, depends on make package
# try to repack x-test, with just toolkit/defines.inc being there

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

@ -497,6 +497,9 @@ canvas.allow=Allow Data Access
canvas.allow.accesskey=A
canvas.remember=Always remember my decision
# Spoof Accept-Language prompt
privacy.spoof_english=Changing your language setting to English will make you more difficult to identify and enhance your privacy. Do you want to request English language versions of web pages?
identity.identified.verifier=Verified by: %S
identity.identified.verified_by_you=You have added a security exception for this site.
identity.identified.state_and_country=%S, %S

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

@ -15,4 +15,4 @@
<!ENTITY languages.customize.selectLanguage.label "Select a language to add…">
<!ENTITY languages.customize.addButton.label "Add">
<!ENTITY languages.customize.addButton.accesskey "A">
<!ENTITY languages.customize.spoofEnglish "Request English versions of web pages for enhanced privacy">

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

@ -5,32 +5,12 @@
<!-- milon.morfix.co.il MozSearch plugin
Compatible with Mozilla Firefox 2+
Tomer Cohen, September 2006 - http://mozilla.org.il -->
<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
<ShortName>מילון מורפיקס</ShortName>
<Description></Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+g
vaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1gkdCRktdt52QwAAACR0
RVh0Q29tbWVudABUb21lciBDb2hlbgp0b21lcmNAZ21haWwuY29tUau7swAAAxxJ
REFUOMttk91rm2UYxq/7eZ/3fZO8SZqlcflct2at/YjokDJBPNAyHW4Hgw31wP9B
kP0Bngw2QWHsxFOPdjJPhG1MEaqIddOWDbqxOmrStE3atGk+lrxJ3o/neTxYtlXx
hpv74Oa64Oa+foQDpZQCAALAAPDhJADiQCsieqGh/4g5gCCAmO85cdFvhZVUJM0R
O2AGGsTQJFAPgP/chA6IdQBxr7MzIde+m9Vqi+OsUxwl4ULo0dZecK4kXvvsYTqb
faJpWuO5CQeAXrerBa1QzKuvnmD3L79n7P55grqVDKRrASAO6qfZcmV/69bY2utf
BkLH37jfdBpNAJKqb09TMZM2kl9cyR+tfnNB37pzBv3GEQCaAgQ9O8sA4ChQ8fF+
9IdL5vTNTlquCiUG2sUwo+ZGVTemvUzSXniX7NqbAPi+jcqDCisZnLXCpjIARAkI
jZiOXyw1d5YIVWn6fQYACsCxSFUjuxYFoA181H4pmUsL1uc//n7k65/7RvoJABtA
iGvInrS8XGptKjxWn2EcAJ6mQiogGgTpAkC372GjTIWVs+c/fliYmR11/thN4dFX
efiuxYBgBH7o7NxpY/7UB8QBQHZcLJRT0zFnaqrbE/H1QWyCItnruUzW1Q2DfCsB
MAOAKxXg+hKOyTX/cDKp+A1KKxUPQ7fzj47K1pzrdNHCYeTe+vSiETAPOY1iRt+7
Ow7hWgAcV2Bvs2PVzEjcJkaSz9+4Tp7jUDqTIfb420uB7dtzuqoaJq721E/XFEkn
Rp1yGsLVQahtNdVff4vJ4ju5XDcSjChemJkBAO5sL0eM+vejrL2SgvQPvUypYlBK
Athp2Hhwd8u6xyfPrR8fHx+AoPgwksrr7Qv96UYPwm0PGWAApFQYeAL17bZa/W3T
uree+GT59Pz79WQyKRhj4MMvuvKVk5srzfyi2N3dAxAeGvgKsEvt4HZZ5Ivs1Y/W
z5z6sD5bKDicc3WQBVJSBsqVamxp8ddou93ShzsJYo5hjdj5Y2OdyYmJQSKREJqm
qf+jkQAw3/eZEPIlrgTFGJOapiki+hfKAPAPFp9sbyN2GzAAAAAASUVORK5CYII=
</Image>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAIAEBAAAAEAIACzAgAAJgAAACAgAAABACAAFQYAANkCAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAJ6SURBVDiNpZI7aN91FMU/9/H952URunQQE0qKhpYiFtFFRQe36iJa6upcRIoIulRXncW1gw5KKJWCIKhRFB9FEQpW0LZ2iAEflERo8s/ve+91+MXn6oWz3MfhcM6F/1kC8PD+k0ci67mqWgEoles15Vlb4IClPFJVc5VxVSIvrv2++t2/CB649cQxETknyGKSiAhmhqpcUtHbQPZXFZlBJb9l9nO70zzz2fbb6wC2NHfkNUHvKwJVxd1wV9zbATObUxNUBRkxr2LHROvBg/N3vPvj9uUtlWJBqL1jx5vTWqM1o02cNmkjWsPdEAP3dk9lexnOqC3NHl4X1ePmNu9u42JzmjuTyQzNG2b+l2MFVCVZHFqc3bhg16ffXjt4y9FNNz8+ynd84kzaDGJyUdReQvIbUb0LZLYqqSooZqrY9JHYNkQFVUVNcXPMdcPdTp796pUrAE8efmbTzV/tOiCqIEEVTyiAaJmIgMiYgjqm7fuzjy5c+zsv+RxJRHTMHhBhWf/7GFVFUSTFQ2v8Y173C8rowl4HthwgAkyTyqSyyEhSOmtrZ/pTd59eyl5PZ/ZTPTqZSY4eoFXvjPZGkCZkJpFB9KCKfuLQqeVhd7hgZSt96PQeI3kkVbWTwus+SinJSEICRFAGtGIQ5DEbbGU7bpKR9AgiAlKIzPN24+cvHCCrtiSCTlGAlRKhN7Eqw+kx7KlLCBhi93Lm8MLHrHUF2Gfty4IPK4XowXQYhmF3562hOL+zu7Peh6QPQQxJ7/2Dkunjn2yuXgUwgB+2L00X9c73cG7PzH2Qp9//5c03rmx+fWN5/uinEf3eHpER8aJ4PP/Rr6s//ZnEH4VnUn6KMJ1eAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAF3ElEQVRYhc2WW4idVxXHf2vtc6bJ1FwmVhqoSVD70DKpEPpgpRpDUaQ+iLZMaksf+tAYoUIQERQRCr4Z1IdQhYpGLC2paUuJFcT2YaSTlkBCq21iKcHamLb2emYaE2bmfHv9ffiuZ86M9k03Z/Nd+M76/9Zlr73hfzys+7B78627IH1ZaKewywwEIDCHokDHrprngaMczQB7PjKzVeHbXNqeIclsyYe8nq14V/3h28ffOXbhAwHcvOXmjRdjww8Fdxs+CSqVux+a4WZZxg9Stoci8R0z+yLoasNQhSqJULwH9pIpThTKDx1fePTkmgB72NOLqSvvc9LXQ3kV6UrcHTPHTAtYOt8znxYiFM13UglggFTGL8dwPuA3Qy8OnnjvsfNjtndv3rsb7EnBBCvEW2HD3DAMd8PMERrJXxkAIbUgklAEyAmGLwXsmxscnetquOArYGuK1zO5k1L9bCR3PKVmpua+811yLDmywOhf4/iRz07tvXEUQLpmZdi7wmMzeSWSGqiUKsBqNt91/mcu3NJVFvaLz6yf2d5qmS2Oek4Tcq9n8tY7r711Ui9VIKkBa+YIeGlPBO5+rU3Y9xoAxDNeZbMUXulx6qQhNcZT530TkZRwL4HSGhGUCdzu/NyWmU+XAOv0aFi8YeYtRLnk2vsqEmVUWvFaNKVxb807NupCrmYifSiLuwDSqxfPzG+/bOc5Qzd56k16lVer89mNQEpj4e2nPsn7pJRGUzi2RoyyT1RvFFMf3XT9kQRwbun0mR0bpl90/EsppfVN3n2ld3UNlDCYXcD5nSmOyXTajA+7+VRJ0hFXi1E3K7ApDYdP9hrI7C+QWDCzqdoDG0mDN6FNnhD8tdfr7dvyr8WTh84eWgK4Zdc9O3pL6UfJ015JzX+rsNSVVv9Izk1e609k77uZd0VHxKtrWVx2KfXZ/+DzB4/X4gCPPXffq/1l7RM65Z5K4BX1VDc0zJD8hgaAdZ24WZlMs9F3hpG8j9z+cH7jpmdZZTx49tD75nY4eV0TlceVTZqLMHS1j/y7EqFTQnVR1V4kT5jshdnZe4vVAKpxRgq8Xlkdm3UarNwqtvraNjrej92vsmN1Ryh11NYwYwC9/wKgzp2q5/+sDYBzveFVtdMuvRGTwmBpFECtkLrvyi3uA8nPTH9rC2Z3hnID0AVvlyII3mwBFivZUmt0S5UIgSKIHBSxevrv2PXtHcn0c5PtjIgGvuKvDSNRZ+hU0wcW18FEBrmw5nTTQrV7fYyF4WufPPApw2/Pw3yLiW05Su9VN52xCFYQZk+1jWgR1FNLHEIWRBhmAVGecrIHhdoI3Hbdgf0KO5gsbcixTI5MhIgIIgKFCJVT1bNkiFggp04nBEIZizorUXWvoD50mRmRS8MAM9fe8wUV8VPM1i9psRSLKFNWAYRqkCghJEyGFLOX3t/095EiVBPqlfmvjNUCIcG9noNvIl9f5KIBU6gCqY9k4/ayigL88CnuH/ZGAUoxCwMcLEbaklkJUOScv/qJf16Rs67D2oNpGe42At1I1NEpvdfjT8/rCYAGwBlKWCgEXhabwgiEVWvGzMgWZEUeZp/suyZFbgpTtB7X4Y6o3wXIyMqvKdv34bd5FMAuHxRcmkdUOe40zno7MCMXBaZ4u7gYA98YC45dKUVzKo6q4luAaKKhiIsB35i78PDLrePVmJ3/9bzLnil3KY1UcoTIVRiXY3kBsxNPDe5fyDmfVEDOmci5vVb9oilYQeRYCPLdc4OHn+imfaQIe/CTUD7npA59bVgoIIr41e//8csXAYbBj4fF8rsKI+cgRzTiOedSPIyIOK0obnt68MgRVozUfXhl6fRg27rpP2PcYPgVTUMuLzmTH/Dh8nf/tnhmCeCVC8+/8bHJ6bOIGyU2Nqug6iWhGEj5cM9j/5/mH3lupTis2OLqsefyma3FhN9lituBKbC/mPEzH7z1x1lmx/rw5zfd8XH1OBDErZI2h3hZ4nH1ODL3Tpvv/8vxb8af5VHCgdKPAAAAAElFTkSuQmCC</Image>
<Url type="text/html" method="GET" template="http://milon.morfix.co.il/default.aspx" resultdomain="morfix.co.il">
<Param name="q" value="{searchTerms}"/>
</Url>

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

@ -6,11 +6,11 @@
<ShortName>楽天市場</ShortName>
<Description>楽天市場 商品検索</Description>
<InputEncoding>EUC-JP</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,R0lGODlhEAAQALMOAOefn9psbMswMMMQEPjj4/PPz++/v+OPj99/f9+AgMcgIM9AQOuvr////wAAAL8AACH5BAEAAA4ALAAAAAAQABAAAARf0EnJ0FqIze2YemCoaBsQniEwMeIloOQHJk1NvKDSnTRQNIZThddYPAiNk4UYCDQIpwux1ghEEUTGc6BkhWiLA1DokD3Ag5/1odvlFlzFAkdymFAn1caDH3FWFhh1EhEAOw==</Image>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAIAEBAAAAEAIACYAgAAJgAAACAgAAABACAARwUAAL4CAACJUE5HDQoaCgAAAA1JSERSAAAAEAAAABAIBgAAAB/z/2EAAAJfSURBVDiNdZFLSJRhFIaf8/9jOoFa3tLEBC/JCEU5yUgGahIS5TIqiCxTNIiKpCiiVWJBpV0Iw9vGnbMqokW6kYRJZCK6qRNmXhJprMzQ0XH8vxZOo47T2Z7zPuc95xWCytV4J3ug6WE5IoWiSFWiDIEhFJ3Z1TWt6VUXR1fPS0DoehE+cLT6NnBOBFMwGADFXNweW11eU0ediKgAwC9+KkJJSOE6jmordY5WiIjSAQ70vLorwgkApQyiMi1EZWSxMXkb4THxLEx9B8MAEb9t2f3D6fjd+ubTaxl83GBxtTS8R9ABDK+X3PttJBUfDGycGx/BUXUMz+TEigulZjLKr6TpJZP91xDyA42lJZJLSjEnJNF3qZJf75wkFR8iMiOLsWd2RNeXXYiEa5oxblJQEPjkqjJ8i7gd3SzNe9iybz/Rlp2Iae1vp5yOIpMoUglBEE0nMi2TiMStbN6Vy5/P/SjfIhK2YdWQpJiWc15PCIuKpsDeBcDizDQf62+imcKC4zA0UXwJcQE+zxyDT+5heL3Mfhtj+sPbQAorBhjWELpCAYyFeQYb6+l/dItNlh1Yzl/F8PnWzMTm2Dq17KqaZqXUfDBaNB3NZGKovQm3o5v0srMk5BeCUn73uDNPXegQAEflketTzt5aAKUU5oRE9Agzs2NfAdDDIzAnJePzzOGZnEBEiLHaTuY329vFL9KeW1NbgNOhzgmuWKutdm+z/QaAtuxYjMPOkTMxVttlpdTM/4QK3LE5eWX/xMD6/FytD+LdvT3Hf/b1FikhRcBAMRxrtb3cXlFjj8vLW7PgL85j5b2Pva1GAAAAAElFTkSuQmCCiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFDklEQVRYha2Wa2xUVRSFv33ubadT2lLCQwSngwQRCYVCiwIqSIgPEHkkPDQQoyYYjBgjCBgfGFCDkT/8UjCRVE0UwYhUXlEiEiJRbCkgNEKgQikoD0npTDvtzL13+6N0+hqmM4SVTHLu3mevte6dk7O3kCK+n3BvrmluHI/HQ4KMVNGgQL6qeMBVhDNApYi3v7yitnw1eKnwSncbto0KDrIs7yVgviDBVEgVPWJUNjl+f+msgydDt2Rg3yTscCiwQpHXBXqlItzVCKeM8Pb0ipqtaRkoKx5cgBcrFZHJtyKcABsiTTmvzquqinZroKw4OAxPd4ow+DaJ34DuznSicx8/dqmhfdS0f9hVOPAuUW/X7RcHkKlRK3PzvknY7aNW66K8uDjjuolsF6Soa63gOTGchga8aHOXn8aigCCW1aW0E8/Q5mhe1tf/1O+Nh1oXZcWBN0RlbaI6L9pMr1ElFMx6uktOXZdwTTWXD/xM/akqLH82YkwClhv7QfG8yTOO1O6PG9hWMiBgu9YJRHITFTnhEIPmPkvR++tvSuxGGjnz+Qb++ngdYtnJTSiHKiprxq8GzwBYnrXkZuJA/C9IBsufzdDFSxmxYg1uUyTpXhHuLykOPgFgtgzvmwOyIGlFJzjhELU7vuX89m+4+NMOYvXX47nBCxfRb8IjuJHkJvD0RQDb588aL8rAdAxELv9LxfLFuLEYiJA/vJBxn3xF9oAAAIHZz3D5133JSUQn7Srq39cYZWI64gBiDHZOLhm5eWTm9aTuz0rObi6N53vecx9Wdg/US9YOJN+xMkYbRUama6CrIYtYuL7t2baSHsL4PkyhDRpMoSd1gHoeTjiE5zioemTm9SIwY34833ihBqexAdufnZzI8wpsID8tdSAzL5+7Fy5CHQfL72fg1Nn0Khwdz1/YUwZJP38rJM+WFPt2e/j69GXkWwnvLK4dLefinu1Y3b09oKKeAbmaroHEbMqV3w9QvnQRbiya2hlQrhmgOl0tz4nRWHuOWLht1lDg7JYvCFWfwvJlpUZkqDYoh9M10HjhPL/MmcKBBU/SdPkSACJC4cr3yBsyDLepKSUeceWoUfW6uTESQBUvFqPu+BGOrlkOqgBk9evPyFUfgWo3dwAAFxujkWMmt2dtJXAiXQ9iDBl5Pbn4Yxlnvvw0Hr/j4SkMeeFlnHDSURBV3Tmv6krYTN6PI8rGdA20ws7uQdX6D6g7fiQeG7ZkJb3HTsBpbEhYo6BGZCPcmIgcv79U0XNJ7CJW2yBjZfnja7Fs3KYIlateiwtaPh8l6zaS1a8/6jhd6AT9bvrhmoqW9Q38UFQwB0PC6dVzHHoEgvQe/QAAsXCISwf2tlw20kLhNkXoM/ZBehQMQlUxGZn898dBwjV/Y+w286pabxvGTKs4f6aDAYCy0YFPRWRRV8uCxmK4zS2nW4xJeNG4zU0d3tjK8iO2HT+kAB76/MzD50tbnzsMiHbI94qbGw0iPNaBWRWxbWw7J9EHahP0ZYGvU7CduCprZ1a2iUOnqXja6dPNrt8/R1V3JlW6BaiydkZlzZud4wnb4L5J2KH6wIcisuw2SNehZtlTlec2Jcom7cPbiwOPGo81iIy7JWllq2eZd2aVnz15sz3dDgLvgikZE5yp6HOCTgRJ2r5VqRV0jyfms5mHz/3WHX9ak8ju4oI7Y64UYXSEqAYVyRFQhGsK1YIes2zf0WmHTtd3z9aC/wGRJv+fU1BOjgAAAABJRU5ErkJggg==</Image>
<Url type="text/html" method="GET" template="https://pt.afl.rakuten.co.jp/c/013ca98b.cd7c5f0c/" resultdomain="rakuten.co.jp">
<Param name="sitem" value="{searchTerms}"/>
<Param name="sv" value="2"/>
<Param name="p" value="0"/>
</Url>
<SearchForm>http://www.rakuten.co.jp/</SearchForm>
<SearchForm>https://www.rakuten.co.jp/</SearchForm>
</SearchPlugin>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.ru/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://yandex.ru/yandsearch" resultdomain="yandex.ru">
<Url type="text/html" method="GET" template="https://yandex.ru/search" resultdomain="yandex.ru">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.by/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://yandex.by/yandsearch" resultdomain="yandex.by">
<Url type="text/html" method="GET" template="https://yandex.by/search" resultdomain="yandex.by">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.kz/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://yandex.kz/yandsearch" resultdomain="yandex.kz">
<Url type="text/html" method="GET" template="https://yandex.kz/search" resultdomain="yandex.kz">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.ru/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://yandex.ru/yandsearch" resultdomain="yandex.ru">
<Url type="text/html" method="GET" template="https://yandex.ru/search" resultdomain="yandex.ru">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.com.tr/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://yandex.com.tr/yandsearch" resultdomain="yandex.com.tr">
<Url type="text/html" method="GET" template="https://yandex.com.tr/search" resultdomain="yandex.com.tr">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -10,7 +10,7 @@
<Url type="application/x-suggestions+json" method="GET" template="https://suggest.yandex.ua/suggest-ff.cgi">
<Param name="part" value="{searchTerms}"/>
</Url>
<Url type="text/html" method="GET" template="https://www.yandex.ua/yandsearch" resultdomain="yandex.ua">
<Url type="text/html" method="GET" template="https://www.yandex.ua/search" resultdomain="yandex.ua">
<MozParam name="clid" condition="purpose" purpose="searchbar" value="2186618"/>
<MozParam name="clid" condition="purpose" purpose="keyword" value="2186621"/>
<MozParam name="clid" condition="purpose" purpose="contextmenu" value="2186623"/>

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

@ -4,10 +4,7 @@
%include ../../../shared/incontentprefs/dialog.inc.css
label,
textbox,
description,
.tab-text,
menulist label {
font-size: 1.11rem;
:root > * {
font-size: 1.05em;
}

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

@ -4,19 +4,8 @@
%include ../../../shared/incontentprefs/preferences.inc.css
html *,
page *,
window * {
font-size: 1.11rem;
}
caption label {
font-size: 1.27rem;
}
.tip-caption,
.help-label {
font-size: 1rem;
:root > * {
font-size: 1.11em;
}
.treecol-sortdirection {
@ -24,20 +13,9 @@ caption label {
-moz-appearance: none;
}
.actionsMenu {
font-family: "Clear Sans", sans-serif;
font-size: 1.25rem;
line-height: 22px;
}
.actionsMenu > .menulist-label-box > .menulist-icon {
margin-top: 1px;
margin-inline-start: 1px;
margin-inline-end: 6px;
}
.actionsMenu > .menulist-label-box > .menulist-label {
margin-top: 2px !important;
margin-inline-end: 8px;
}
filefield + button {

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

@ -9,12 +9,8 @@ prefwindow,
font: message-box !important;
}
label,
textbox,
description,
.tab-text,
menulist label {
font-size: 1.36rem;
:root > * {
font-size: 1.18em;
}
caption {

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

@ -4,19 +4,8 @@
%include ../../../shared/incontentprefs/preferences.inc.css
html *,
page *,
window * {
font-size: 1.36rem;
}
caption label {
font-size: 1.55rem;
}
.tip-caption,
.help-label {
font-size: 1.18rem;
:root > * {
font-size: 1.36em;
}
.actionsMenu > .menulist-label-box > .menulist-icon {

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

@ -1,59 +1,62 @@
<!-- 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" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 173.87 156.5">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 173.9 156.5">
<style>
.cls-1{fill:#eaeaee;}
.cls-2{fill:#fff;}
.cls-3{fill:url(#linear-gradient);}
.cls-4{fill:#f9f9fa;}
.cls-5{fill:url(#New_Gradient_Swatch_1);}
.cls-6{fill:url(#New_Gradient_Swatch_1-2);}
.cls-7{fill:url(#New_Gradient_Swatch_1-3);}
.cls-8{fill:url(#New_Gradient_Swatch_1-4);}
.cls-9{fill:url(#linear-gradient-2);}
.cls-10{fill:url(#New_Gradient_Swatch_1-5);}
.st0{opacity:0.1;fill:#0C0C0D;enable-background:new ;} .st1{fill:#FFFFFF;} .st2{fill:url(#SVGID_1_);} .st3{fill:#F9F9FA;} .st4{fill:url(#SVGID_2_);} .st5{fill:url(#SVGID_3_);} .st6{fill:url(#SVGID_4_);} .st7{fill:url(#SVGID_5_);} .st8{fill:url(#SVGID_6_);} .st9{fill:url(#SVGID_7_);}
</style>
<defs>
<linearGradient id="linear-gradient" x1="55.45" y1="55.54" x2="128.28" y2="128.38" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ccfbff"/>
<stop offset="1" stop-color="#c9e4ff"/>
<path class="st0" d="M140.9 152h-69c-.6 0-1-.4-1-1s.4-1 1-1H141c.6 0 1 .4 1 1s-.5 1-1.1 1zm-9.3-5.1h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-15.7 9.6h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-10 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.2.5-.5.5zm-20 0h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zm-7 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5z"/>
<path class="st1" d="M85 20.4h21.3s-6.7-14.9 7.5-16.8c12.6-1.7 17.6 11.3 17.6 11.3s1.5-7.5 9-6.1 12.9 13.3 12.9 13.3h18.6"/>
<path class="st0" d="M172.2 18.6h-4c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h4c.3 0 .5.2.5.5s-.2.5-.5.5zm-13 0h-1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h1c.3 0 .5.2.5.5s-.2.5-.5.5zm-5 0h-.8c-.1-.1-.2-.1-.2-.2-.1-.2-.5-1-1.2-2.1-.1-.2-.1-.5.2-.7.2-.1.5-.1.7.2.5.8.9 1.5 1.1 1.9h.2c.3 0 .5.2.5.5s-.2.4-.5.4zm-47.5-.6h-1.3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h.6c-.1-.2-.2-.6-.3-.9-.1-.3.1-.6.3-.7.3-.1.6.1.7.3.3.9.6 1.5.6 1.5.1.3 0 .5-.3.7-.1.1-.2.1-.3.1zm-9.3 0h-12c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h12c.3 0 .5.2.5.5s-.3.5-.5.5zm7.8-5.5c-.3 0-.5-.2-.5-.4 0-.3-.1-.7-.1-1s.2-.5.5-.5.5.2.5.5 0 .6.1 1c.1.2-.1.4-.5.4.1.1.1.1 0 0zm26.2-1c-.2 0-.4-.1-.4-.3-.1-.2-.3-.5-.4-.9-.1-.2 0-.5.2-.7.2-.1.5 0 .7.2.2.3.3.6.5.9.1.2 0 .5-.2.7-.3.1-.3.1-.4.1zm16.1-1.3c-.1 0-.3 0-.4-.1-1.7-1.8-4-3.1-6.4-3.7-1.3-.3-2.6-.2-3.9.2-.3.1-.5-.1-.6-.3-.1-.3.1-.5.3-.6 1.4-.4 2.9-.5 4.4-.2 2.6.6 5.1 2 6.9 4 .2.2.2.5 0 .7-.1-.1-.2 0-.3 0zm-18.8-3c-.2 0-.3-.1-.4-.2-.6-.8-1.3-1.5-2-2.1-.2-.2-.1-.5.1-.7.2-.1.4-.1.6 0 .8.7 1.5 1.4 2.1 2.2.2.2.1.5-.1.7 0 .1-.2.1-.3.1zm-20.5-3.8c-.3 0-.5-.2-.5-.5 0-.2.1-.3.2-.4 1.8-1.3 4-2.2 6.2-2.4 1.9-.3 3.8-.2 5.7.2.3.1.5.3.4.6s-.3.5-.6.4c-1.7-.4-3.5-.4-5.3-.2-2.1.2-4.1.9-5.7 2.2-.2.1-.3.1-.4.1z"/>
<path class="st1" d="M172.9 22.4H85c-.6 0-1-.4-1-1s.4-1 1-1h87.9c.6 0 1 .4 1 1s-.5 1-1 1zM.8 37.7h11.9s-3.7-8.3 4.2-9.4c7-1 9.8 6.3 9.8 6.3s.8-4.2 5-3.4 7.2 7.4 7.2 7.4h10.3"/>
<path class="st0" d="M13 36.4H1.1c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h11.5c.2-.2.5-.2.7 0l.1.1v.1c.1.3 0 .5-.3.7 0 .1-.1.1-.1.1zm32.9-.2h-3c-.3 0-.5-.2-.5-.5s.2-.5.5-.5h3c.3 0 .5.2.5.5s-.2.5-.5.5zM27 33h-.1c-.3-.1-.4-.4-.3-.6.5-2 2.3-3.5 4.4-3.5.4 0 .7 0 1.1.1 1.9.5 3.6 1.5 4.9 3 .2.2.2.5 0 .7s-.5.2-.7 0c-1.1-1.3-2.6-2.3-4.3-2.7-.3-.1-.6-.1-.9-.1-1.7 0-3.1 1.2-3.4 2.8-.3.2-.5.3-.7.3zm-13.6-4.3c-.3 0-.5-.2-.5-.5 0-.1.1-.3.1-.4.8-.8 1.8-1.3 2.8-1.6.3-.1.6.1.6.4s-.1.6-.4.6c-.9.2-1.7.7-2.4 1.3.1.2 0 .2-.2.2zm7.5-1.3h-.1c-.3-.1-.6-.2-.9-.2-.3-.1-.5-.3-.4-.6.1-.3.3-.5.6-.4.3.1.7.2 1 .3.3 0 .5.3.4.6 0 .1-.3.3-.6.3z"/>
<path class="st1" d="M49.9 39.7H1c-.6 0-1-.4-1-1s.4-1 1-1h48.8c.6 0 1 .4 1 1s-.4 1-.9 1zm85.5 37.5h-15.3V60.3c0-4.2-3.4-7.5-7.6-7.5H51.1c-4.2 0-7.5 3.4-7.5 7.5V101c0 1.3.4 2.6 1 3.7-.4.5-.8 1-1 1.6l-6.9 16.1c-.3.7-.5 1.5-.5 2.3v1.1c.1 3.4 2.8 6.1 6.2 6h60v3.2c0 4.1 3.3 7.4 7.4 7.4h25.6c4.1 0 7.4-3.3 7.4-7.4V84.7c.1-4.2-3.2-7.5-7.4-7.5z"/>
<path class="st1" d="M50.8 56.5h61.4c2 0 3.6 1.6 3.6 3.5v40.7c0 2-1.6 3.6-3.6 3.6H50.8c-2 0-3.5-1.6-3.5-3.6V60.1c0-2 1.6-3.6 3.5-3.6z"/>
<path class="st1" d="M52.7 62.5h57.7c1.2 0 2.1.9 2.1 2.1V99c0 1.2-.9 2.1-2.1 2.1H52.7c-1.2 0-2.1-.9-2.1-2.1V64.6c0-1.1 1-2.1 2.1-2.1z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="55.4468" y1="665.5432" x2="128.2768" y2="738.3832" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#CCFBFF"/>
<stop offset="1" stop-color="#C9E4FF"/>
</linearGradient>
<path class="st2" d="M110.4 63.5c.6 0 1.1.5 1.1 1.1V99c0 .6-.5 1.1-1.1 1.1H52.7c-.6 0-1.1-.5-1.1-1.1V64.6c0-.6.5-1.1 1.1-1.1h57.7"/>
<path class="st3" d="M115.7 107.6c-.4-.8-1.2-1.3-2.1-1.2H49c-.9 0-1.7.5-2.1 1.3L40 123.8c-.1.2-.1.5-.1.7v1.1c.1 1.2 1 2.1 2.2 2H121c1.2.1 2.2-.8 2.2-2v-1c0-.3-.1-.5-.2-.7l-7.3-16.3z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-4.5021" y1="627.6644" x2="182.4979" y2="797.1644" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#00C8D7"/>
<stop offset="1" stop-color="#0A84FF"/>
</linearGradient>
<path class="st4" d="M124.9 122.9l-7.3-16.1c-.3-.8-.9-1.4-1.6-1.8 1.2-1.1 1.9-2.6 1.9-4.2V60.1c0-3.1-2.5-5.5-5.6-5.5H50.9c-3.1 0-5.5 2.5-5.5 5.5v40.7c0 1.5.6 3 1.7 4-.9.4-1.6 1.1-2 2L38.2 123c-.2.5-.3 1-.3 1.5v1.1c.1 2.3 1.9 4.1 4.2 4H121c2.3.1 4.2-1.7 4.2-4v-1c0-.6-.1-1.2-.3-1.7zm-1.7 2.6c-.1 1.2-1 2.1-2.2 2H42.1c-1.2.1-2.2-.8-2.2-2v-1.1c0-.2 0-.5.1-.7l6.9-16.1c.4-.8 1.2-1.3 2.1-1.3h64.7c.9 0 1.7.5 2.1 1.2l7.3 16.1c.1.2.2.5.2.7l-.1 1.2zm-75.9-24.7V60.1c0-2 1.6-3.5 3.5-3.5h61.4c2 0 3.6 1.6 3.6 3.5v40.7c0 2-1.6 3.6-3.5 3.6H50.9c-2 0-3.6-1.6-3.6-3.6z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-51.3994" y1="590.94" x2="201.6006" y2="840.94" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#00C8D7"/>
<stop offset="1" stop-color="#0A84FF"/>
</linearGradient>
<path class="st5" d="M94.7 121.8H68.4c-.4 0-.8-.2-.8-.5.3-1.7.5-2.6.8-4.4 0-.2.3-.4.7-.4l25.3-.2c.4 0 .7.2.7.4.2 1.5.4 3 .4 4.5.1.4-.3.6-.8.6zM64 112.4h-3.9c-.3 0-.6.2-.7.4-.1.5-.2.7-.3 1.2s.4.7.9.7h3.8c.3 0 .6-.1.7-.3.1-.5.2-.7.3-1.2s-.3-.8-.8-.8zm9.9 0h-4.1c-.4 0-.7.2-.7.4-.1.5-.1.7-.2 1.2-.1.3.4.6.9.6h3.9c.3 0 .6-.1.7-.4.1-.5.2-.7.3-1.2.1-.4-.3-.7-.8-.6zm20.5 1.4c-.1-.5-.1-.7-.2-1.2 0-.2-.3-.4-.7-.4h-4.1c-.5 0-.9.3-.9.6l.3 1.2c0 .2.3.4.7.4h3.9c.6 0 1.1-.3 1-.6zm-9.9.1l-.2-1.2c0-.2-.4-.4-.8-.4h-3.7c-.4 0-.8.2-.8.4-.1.5-.2.7-.2 1.2-.1.3.3.6.8.6h4.1c.4-.1.8-.3.8-.6zm19.6-.2l-.2-1.2c0-.2-.3-.3-.6-.3h-3.9c-.5 0-1 .3-.9.7l.3 1.2c.1.2.3.3.7.3h3.8c.4-.1.9-.4.8-.7zm-39.1-5h-3.7c-.3 0-.5.1-.6.3-.1.4-.2.7-.3 1.1s.3.6.8.6h3.6c.3 0 .5-.1.7-.3.2-.4.2-.7.4-1.1s-.4-.6-.9-.6zm9.4 0h-3.9c-.4 0-.7.2-.7.4-.1.4-.2.7-.3 1.1s.3.6.8.6h3.8c.3 0 .6-.1.7-.4.1-.4.2-.7.3-1.1s-.3-.6-.7-.6zm19.6 1.4l-.2-1.1c0-.2-.3-.4-.7-.4h-3.9c-.5 0-.9.3-.8.6l.2 1.1c0 .2.3.4.7.4h3.8c.5-.1.9-.3.9-.6zm-9.5.1l-.2-1.1c0-.2-.3-.4-.7-.4H80c-.4 0-.7.2-.8.4-.1.4-.2.7-.3 1.1-.1.3.3.5.8.5h3.9c.5 0 .9-.3.9-.5zm18.7-.1l-.2-1.1c0-.2-.3-.3-.6-.3h-3.7c-.5 0-1 .3-.9.6l.3 1.1c.1.2.3.3.6.3h3.6c.5-.1.9-.4.9-.6zm-48.1 2.4h-3.8c-.3 0-.6.1-.7.4-.2.4-.3.8-.4 1.2-.1.3.4.7.9.7h3.7c.3 0 .6-.2.6-.4.1-.4.2-.8.4-1.2.2-.5-.2-.8-.7-.7zm1.3-3.7h-3.5c-.2 0-.5.1-.6.3-.1.4-.2.7-.4 1.1-.1.3.2.6.7.6h3.5c.3 0 .5-.1.7-.3.2-.4.3-.7.5-1.1s-.4-.7-.9-.6zm50.9 4.1c.1.4.3.8.3 1.1 0 .2.3.3.6.3h3.7c.5 0 1-.3.9-.6-.1-.4-.2-.8-.3-1.1-.1-.2-.4-.4-.7-.3h-3.7c-.5-.1-.9.2-.8.6zm-1.1-3.7c.1.4.2.7.4 1.1.1.2.4.3.6.3h3.4c.5 0 .8-.3.8-.6-.1-.4-.2-.7-.3-1.1 0-.2-.2-.3-.6-.3H107c-.4 0-.9.3-.8.6z"/>
<g>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-22.6206" y1="563.3309" x2="225.3794" y2="813.3309" gradientTransform="translate(0 -610)">
<stop offset="0" stop-color="#00C8D7"/>
<stop offset="1" stop-color="#0A84FF"/>
</linearGradient>
<linearGradient id="New_Gradient_Swatch_1" x1="-4.48" y1="17.64" x2="182.52" y2="187.14" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#00c8d7"/>
<stop offset="1" stop-color="#0a84ff"/>
<circle class="st6" cx="82.6" cy="59.4" r="1.2"/>
</g>
<path class="st1" d="M109.6 80h25.6c2.5 0 4.4 2 4.4 4.4v50.3c0 2.5-2 4.4-4.4 4.4h-25.6c-2.5 0-4.4-2-4.4-4.4V84.4c-.1-2.4 1.9-4.4 4.4-4.4z"/>
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-19.2553" y1="590.7758" x2="221.2447" y2="809.2758" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#00C8D7"/>
<stop offset="1" stop-color="#0A84FF"/>
</linearGradient>
<path class="st7" d="M135.1 81c1.9 0 3.4 1.5 3.4 3.4v50.3c0 1.9-1.5 3.4-3.4 3.4h-25.6c-1.9 0-3.4-1.5-3.4-3.4V84.4c0-1.9 1.5-3.4 3.4-3.4h25.6m0-2h-25.6c-3 0-5.4 2.4-5.4 5.4v50.3c0 3 2.4 5.4 5.4 5.4h25.6c3 0 5.4-2.4 5.4-5.4V84.4c.1-3-2.4-5.4-5.4-5.4z"/>
<g>
<path class="st1" d="M111.1 84.8h22.4c.9 0 1.7.8 1.7 1.7v41.9c0 .9-.8 1.7-1.7 1.7h-22.4c-.9 0-1.7-.8-1.7-1.7V86.5c0-.9.8-1.7 1.7-1.7z"/>
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="62.995" y1="657.995" x2="135.835" y2="730.835" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#CCFBFF"/>
<stop offset="1" stop-color="#C9E4FF"/>
</linearGradient>
<linearGradient id="New_Gradient_Swatch_1-2" x1="-51.35" y1="-19.11" x2="201.65" y2="230.89" xlink:href="#New_Gradient_Swatch_1"/>
<linearGradient id="New_Gradient_Swatch_1-3" x1="-22.65" y1="-46.64" x2="225.35" y2="203.36" xlink:href="#New_Gradient_Swatch_1"/>
<linearGradient id="New_Gradient_Swatch_1-4" x1="-19.25" y1="-19.23" x2="221.25" y2="199.27" xlink:href="#New_Gradient_Swatch_1"/>
<linearGradient id="linear-gradient-2" x1="63.01" y1="47.98" x2="135.85" y2="120.82" xlink:href="#linear-gradient"/>
<linearGradient id="New_Gradient_Swatch_1-5" x1="-73.41" y1="91.75" x2="262.92" y2="91.75" xlink:href="#New_Gradient_Swatch_1"/>
</defs>
<path class="cls-1" d="M140.93,151.83H71.85a1,1,0,0,1,0-2h69.08a1,1,0,0,1,0,2Z" transform="translate(0.02 0.17)"/>
<path class="cls-1" d="M131.6,146.72h-12a.5.5,0,0,1,0-1h12a.5.5,0,1,1,0,1Z" transform="translate(0.02 0.17)"/>
<path class="cls-1" d="M115.89,156.33h-12a.5.5,0,1,1,0-1h12a.5.5,0,0,1,0,1Zm-20,0h-3a.5.5,0,0,1,0-1h3a.5.5,0,1,1,0,1Zm-7,0h-1a.5.5,0,0,1,0-1h1a.5.5,0,1,1,0,1Zm-10,0h-12a.5.5,0,0,1,0-1h12a.5.5,0,1,1,0,1Zm-20,0h-3a.5.5,0,1,1,0-1h3a.5.5,0,0,1,0,1Zm-7,0h-1a.5.5,0,1,1,0-1h1a.5.5,0,0,1,0,1Zm-10,0h-12a.5.5,0,1,1,0-1h12a.5.5,0,0,1,0,1Zm-20,0h-3a.5.5,0,1,1,0-1h3a.5.5,0,0,1,0,1Zm-7,0h-1a.5.5,0,1,1,0-1h1a.5.5,0,0,1,0,1Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M85,20.23H106.3S99.63,5.33,113.8,3.4c12.63-1.72,17.62,11.27,17.62,11.27s1.5-7.49,9-6.05S153.3,21.94,153.3,21.94h18.57" transform="translate(0.02 0.17)"/>
<path class="cls-1" d="M172.23,18.44h-4a.5.5,0,0,1,0-1h4a.5.5,0,0,1,0,1Zm-13,0h-1a.5.5,0,1,1,0-1h1a.5.5,0,1,1,0,1Zm-5,0h-.56a.5.5,0,0,1-.22-.05.54.54,0,0,1-.23-.23c-.11-.22-.53-1-1.2-2.08a.5.5,0,0,1,.85-.53c.53.84.9,1.52,1.1,1.89h.25a.5.5,0,1,1,0,1Zm-47.56-.61h-1.32a.5.5,0,1,1,0-1h.58c-.09-.25-.2-.56-.32-.92a.5.5,0,1,1,1-.31c.3.93.56,1.52.56,1.53a.5.5,0,0,1-.46.7Zm-9.32,0h-12a.5.5,0,1,1,0-1h12a.5.5,0,1,1,0,1Zm7.87-5.48a.5.5,0,0,1-.5-.44c0-.34-.07-.68-.09-1a.5.5,0,1,1,1-.06c0,.33,0,.65.09,1a.5.5,0,0,1-.44.56Zm26.15-1a.5.5,0,0,1-.45-.28c-.12-.25-.27-.54-.45-.87a.5.5,0,1,1,.88-.48c.19.34.34.65.47.91a.5.5,0,0,1-.45.72ZM147.48,10a.5.5,0,0,1-.35-.14,13.18,13.18,0,0,0-6.43-3.72,7.66,7.66,0,0,0-3.88.16.5.5,0,1,1-.32-.95,8.66,8.66,0,0,1,4.38-.19,14.15,14.15,0,0,1,6.93,4,.5.5,0,0,1-.35.86Zm-18.8-3a.5.5,0,0,1-.39-.19,19.12,19.12,0,0,0-2-2.13A.5.5,0,0,1,127,4a20.34,20.34,0,0,1,2.1,2.24.5.5,0,0,1-.39.81ZM108.19,3.27a.5.5,0,0,1-.31-.89A12.51,12.51,0,0,1,114.1,0a16.12,16.12,0,0,1,5.66.2.5.5,0,1,1-.22,1A15.06,15.06,0,0,0,114.23,1a11.54,11.54,0,0,0-5.73,2.18A.5.5,0,0,1,108.19,3.27Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M172.85,22.23h0L85,22.21a1,1,0,1,1,0-2h0l87.87,0a1,1,0,1,1,0,2Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M.76,37.55H12.62s-3.71-8.29,4.17-9.36c7-1,9.8,6.26,9.8,6.26s.83-4.16,5-3.37,7.16,7.41,7.16,7.41H49.08" transform="translate(0.02 0.17)"/>
<path class="cls-1" d="M13,36.23H1.13a.5.5,0,0,1,0-1H12.59a.5.5,0,0,1,.8.18l0,.12a.5.5,0,0,1-.46.7Zm32.86-.15h-3a.5.5,0,1,1,0-1h3a.5.5,0,1,1,0,1ZM27,32.86l-.14,0a.5.5,0,0,1-.34-.62,4.66,4.66,0,0,1,4.4-3.55,6,6,0,0,1,1.11.11,9.37,9.37,0,0,1,4.88,3,.5.5,0,1,1-.73.69,8.42,8.42,0,0,0-4.34-2.73,5,5,0,0,0-.93-.09,3.63,3.63,0,0,0-3.44,2.84A.5.5,0,0,1,27,32.86ZM13.4,28.53a.5.5,0,0,1-.36-.85,6,6,0,0,1,2.82-1.57.5.5,0,1,1,.26,1,5,5,0,0,0-2.36,1.29A.5.5,0,0,1,13.4,28.53Zm7.52-1.35-.15,0a7.39,7.39,0,0,0-.91-.23.5.5,0,0,1,.19-1,8.41,8.41,0,0,1,1,.26.5.5,0,0,1-.15,1Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M49.84,39.56H1a1,1,0,1,1,0-2H49.84a1,1,0,1,1,0,2Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M135.34,77H120.06V60.18a7.56,7.56,0,0,0-7.55-7.55H51.08a7.56,7.56,0,0,0-7.55,7.55v40.74a7.55,7.55,0,0,0,1,3.67,5.88,5.88,0,0,0-1,1.6l-6.89,16.12a5.73,5.73,0,0,0-.46,2.26v1.05a6.1,6.1,0,0,0,6.22,6h60v3.19a7.45,7.45,0,0,0,7.45,7.45h25.55a7.46,7.46,0,0,0,7.45-7.45V84.49A7.46,7.46,0,0,0,135.34,77Z" transform="translate(0.02 0.17)"/>
<rect class="cls-2" x="47.3" y="56.55" width="68.54" height="47.84" rx="3.55" ry="3.55"/>
<rect class="cls-2" x="50.64" y="62.52" width="61.86" height="38.58" rx="2.09" ry="2.09"/>
<path class="cls-3" d="M110.38,63.35a1.09,1.09,0,0,1,1.09,1.09V98.83a1.09,1.09,0,0,1-1.09,1.09H52.71a1.09,1.09,0,0,1-1.09-1.09V64.44a1.09,1.09,0,0,1,1.09-1.09h57.67" transform="translate(0.02 0.17)"/>
<path class="cls-4" d="M115.72,107.47a2.23,2.23,0,0,0-2.06-1.23H49a2.22,2.22,0,0,0-2.07,1.27L40,123.63a1.76,1.76,0,0,0-.14.69v1.05a2.1,2.1,0,0,0,2.22,2H121a2.1,2.1,0,0,0,2.22-2v-1a1.77,1.77,0,0,0-.16-.73Z" transform="translate(0.02 0.17)"/>
<path class="cls-5" d="M124.88,122.78l-7.34-16.14a4,4,0,0,0-1.64-1.79,5.54,5.54,0,0,0,1.91-4.18V59.93a5.56,5.56,0,0,0-5.55-5.55H50.83a5.56,5.56,0,0,0-5.55,5.55v40.74a5.53,5.53,0,0,0,1.74,4,4,4,0,0,0-2,2l-6.89,16.12a3.75,3.75,0,0,0-.3,1.48v1.05a4.1,4.1,0,0,0,4.22,4H121a4.1,4.1,0,0,0,4.22-4v-1A3.75,3.75,0,0,0,124.88,122.78Zm-1.66,2.59a2.1,2.1,0,0,1-2.22,2H42.09a2.1,2.1,0,0,1-2.22-2v-1.05a1.76,1.76,0,0,1,.14-.69L46.9,107.5A2.22,2.22,0,0,1,49,106.24h64.69a2.23,2.23,0,0,1,2.06,1.23l7.34,16.14a1.77,1.77,0,0,1,.16.73ZM47.27,100.66V59.93a3.55,3.55,0,0,1,3.55-3.55h61.43a3.55,3.55,0,0,1,3.55,3.55v40.74a3.55,3.55,0,0,1-3.55,3.55H50.83A3.55,3.55,0,0,1,47.27,100.66Z" transform="translate(0.02 0.17)"/>
<path class="cls-6" d="M94.71,121.68H68.43c-.43,0-.81-.25-.79-.53.33-1.7.48-2.59.82-4.38,0-.24.3-.43.68-.43l25.34-.19c.38,0,.66.17.66.41a43.55,43.55,0,0,1,.44,4.53C95.55,121.4,95.14,121.68,94.71,121.68ZM64,112.2H60.07c-.34,0-.61.15-.66.36-.11.48-.17.72-.28,1.2s.39.66.91.66l3.82,0c.34,0,.61-.14.67-.35.13-.47.2-.71.34-1.19S64.53,112.2,64,112.2Zm9.85,0-4.07,0c-.38,0-.69.17-.73.4-.09.48-.13.71-.21,1.18-.05.31.37.61.87.6l3.95,0a.73.73,0,0,0,.74-.4c.12-.47.18-.7.31-1.18C74.76,112.46,74.35,112.16,73.83,112.16Zm20.57,1.46c-.06-.46-.1-.69-.16-1.16,0-.23-.33-.39-.71-.39l-4.07,0c-.52,0-.95.3-.88.61l.26,1.16c0,.23.35.39.73.39l3.95,0C94,114.22,94.45,113.93,94.4,113.63Zm-9.93.09-.2-1.17c0-.25-.38-.43-.79-.43l-3.68,0c-.41,0-.76.19-.81.44-.1.47-.15.71-.25,1.17-.06.3.32.57.8.56l4.09,0C84.13,114.28,84.52,114,84.47,113.72Zm19.61-.19-.23-1.15c0-.2-.3-.34-.64-.34H99.3c-.54,0-1,.33-.93.65l.3,1.15c.05.2.32.34.65.34l3.82,0C103.67,114.17,104.14,113.84,104.08,113.53Zm-39.11-5H61.26a.64.64,0,0,0-.64.33c-.13.44-.2.66-.32,1.09s.33.61.83.61h3.62a.66.66,0,0,0,.65-.33c.15-.44.23-.66.39-1.09S65.49,108.53,65,108.53Zm9.36,0H70.46c-.37,0-.67.16-.72.37-.11.44-.16.66-.26,1.1s.33.56.81.56h3.77a.72.72,0,0,0,.72-.37c.13-.44.2-.66.33-1.1S74.83,108.5,74.33,108.5Zm19.61,1.4-.16-1.1c0-.22-.31-.37-.68-.37H89.23c-.5,0-.91.28-.85.58l.24,1.09c0,.21.34.37.7.36h3.77C93.57,110.46,94,110.19,93.94,109.9Zm-9.49.06-.17-1.1c0-.23-.35-.4-.74-.4H80c-.39,0-.73.18-.79.41-.11.44-.17.66-.27,1.1-.07.28.29.53.76.53h3.92C84.12,110.5,84.5,110.25,84.45,110Zm18.67-.13-.22-1.1c0-.2-.28-.33-.61-.33h-3.7c-.52,0-1,.32-.88.62l.29,1.09c.05.19.3.32.63.32h3.62C102.74,110.44,103.19,110.13,103.13,109.83Zm-48.06,2.4H51.32a.71.71,0,0,0-.69.36,9.8,9.8,0,0,0-.39,1.21c-.09.33.37.67.88.67l3.7,0c.33,0,.58-.15.63-.36a7.82,7.82,0,0,1,.39-1.2C56,112.57,55.59,112.23,55.06,112.23Zm1.32-3.68h-3.5a.57.57,0,0,0-.59.32,10,10,0,0,1-.37,1.09c-.12.3.23.61.7.61h3.45a.72.72,0,0,0,.67-.33c.2-.44.29-.66.45-1.09S56.87,108.55,56.38,108.55Zm50.9,4.12a7.26,7.26,0,0,1,.34,1.14c0,.2.29.33.62.33l3.7,0c.51,0,1-.32.9-.63a9.34,9.34,0,0,0-.34-1.14.68.68,0,0,0-.67-.34h-3.74C107.57,112,107.17,112.36,107.28,112.67Zm-1.1-3.66a8.86,8.86,0,0,0,.36,1.09.66.66,0,0,0,.64.32h3.45c.47,0,.84-.3.75-.6a7.35,7.35,0,0,1-.27-1.1c0-.2-.25-.33-.56-.33H107C106.55,108.39,106.1,108.71,106.18,109Z" transform="translate(0.02 0.17)"/>
<circle class="cls-7" cx="82.57" cy="59.42" r="1.15"/>
<rect class="cls-2" x="105.11" y="79.96" width="34.45" height="59.17" rx="4.45" ry="4.45"/>
<path class="cls-8" d="M135.09,80.79a3.45,3.45,0,0,1,3.45,3.45v50.28a3.45,3.45,0,0,1-3.45,3.45H109.53a3.45,3.45,0,0,1-3.45-3.45V84.24a3.45,3.45,0,0,1,3.45-3.45h25.55m0-2H109.53a5.45,5.45,0,0,0-5.45,5.45v50.28a5.45,5.45,0,0,0,5.45,5.45h25.55a5.45,5.45,0,0,0,5.45-5.45V84.24a5.45,5.45,0,0,0-5.45-5.45Z" transform="translate(0.02 0.17)"/>
<rect class="cls-2" x="109.42" y="84.79" width="25.82" height="45.33" rx="1.72" ry="1.72"/>
<path class="cls-9" d="M133.49,85.62a.72.72,0,0,1,.72.72v41.88a.72.72,0,0,1-.72.72H111.12a.72.72,0,0,1-.72-.72V86.34a.72.72,0,0,1,.72-.72h22.37" transform="translate(0.02 0.17)"/>
<path class="cls-10" d="M82.85,97.67a2.47,2.47,0,0,1-1.55-.55L66.32,85a12.45,12.45,0,0,1-3.66-3.66,12.77,12.77,0,0,1,1.67-16,12.69,12.69,0,0,1,17.95,0,.67.67,0,0,0,.49.22.68.68,0,0,0,.48-.21A12.71,12.71,0,1,1,99.26,85L84.41,97.12A2.49,2.49,0,0,1,82.85,97.67Zm41,23.7,11-9a9.67,9.67,0,1,0-12.19-14.9.24.24,0,0,1-.17.08.25.25,0,0,1-.18-.09,9.66,9.66,0,0,0-13.66,0,9.72,9.72,0,0,0-1.27,12.15,9.46,9.46,0,0,0,2.78,2.78l11.09,9a2.09,2.09,0,0,0,2.63,0Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M73.28,62.67a11.66,11.66,0,0,1,8.29,3.44l0,0a1.66,1.66,0,0,0,1.18.5,1.68,1.68,0,0,0,1.19-.5l0,0A11.71,11.71,0,1,1,98.7,84.16L83.78,96.34a1.48,1.48,0,0,1-.93.33,1.45,1.45,0,0,1-.92-.33l-15-12.16a11.41,11.41,0,0,1-3.41-3.4A11.82,11.82,0,0,1,65,66.08a11.65,11.65,0,0,1,8.25-3.41m0-2h0a13.6,13.6,0,0,0-9.66,4,13.77,13.77,0,0,0-1.8,17.22,13.4,13.4,0,0,0,3.91,3.92L80.67,97.9a3.47,3.47,0,0,0,4.35,0L99.89,85.77A13.71,13.71,0,1,0,82.77,64.49a13.62,13.62,0,0,0-9.49-3.82Z" transform="translate(0.02 0.17)"/>
<path class="cls-4" d="M66.31,76h-.16a2,2,0,0,1-1.79-2.11,8.69,8.69,0,0,1,6.8-7.8A2,2,0,1,1,72,69.92a4.8,4.8,0,0,0-3.76,4.31A2,2,0,0,1,66.31,76Z" transform="translate(0.02 0.17)"/>
<path class="cls-2" d="M115.4,95.66a8.64,8.64,0,0,1,6.14,2.55h0a1.23,1.23,0,0,0,.88.37,1.24,1.24,0,0,0,.88-.37h0a8.67,8.67,0,1,1,10.91,13.37l-11.05,9a1.1,1.1,0,0,1-.69.24,1.08,1.08,0,0,1-.68-.24l-11.13-9a8.45,8.45,0,0,1-2.53-2.52,8.76,8.76,0,0,1,1.14-10.89,8.63,8.63,0,0,1,6.11-2.52m0-2h0a10.59,10.59,0,0,0-7.52,3.11,10.72,10.72,0,0,0-1.4,13.4,10.44,10.44,0,0,0,3,3l11,8.94a3.09,3.09,0,0,0,3.87,0l11-9a10.67,10.67,0,1,0-13-16.88,10.59,10.59,0,0,0-7-2.64Z" transform="translate(0.02 0.17)"/>
<path class="cls-4" d="M110.24,105.54h-.12a1.46,1.46,0,0,1-1.33-1.56,6.43,6.43,0,0,1,5-5.78,1.45,1.45,0,1,1,.63,2.83,3.56,3.56,0,0,0-2.78,3.19A1.45,1.45,0,0,1,110.24,105.54Z" transform="translate(0.02 0.17)"/>
<path class="st8" d="M133.5 85.8c.4 0 .7.3.7.7v41.9c0 .4-.3.7-.7.7h-22.4c-.4 0-.7-.3-.7-.7V86.5c0-.4.3-.7.7-.7h22.4"/>
</g>
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-73.41" y1="701.6741" x2="262.92" y2="701.6741" gradientTransform="translate(.02 -609.83)">
<stop offset="0" stop-color="#00C8D7"/>
<stop offset="1" stop-color="#0A84FF"/>
</linearGradient>
<path class="st9" d="M82.9 97.8c-.6 0-1.1-.2-1.6-.6l-15-12.1c-1.5-1-2.7-2.2-3.7-3.7-3.3-5.1-2.6-11.7 1.7-16 5-5 13-5 17.9 0 .1.1.3.2.5.2s.4-.1.5-.2c5.1-4.8 13.1-4.6 18 .5s4.6 13.1-.5 18c-.5.4-1 .9-1.5 1.2L84.4 97.3c-.4.3-1 .5-1.5.5zm41 23.7l11-9c4.4-3 5.6-9 2.7-13.4-3-4.4-9-5.6-13.4-2.7-.5.3-1 .7-1.4 1.2 0 0-.1.1-.2.1s-.1 0-.2-.1c-3.8-3.8-9.9-3.8-13.7 0-3.2 3.2-3.8 8.3-1.3 12.2.7 1.1 1.7 2.1 2.8 2.8l11.1 9c.7.6 1.8.6 2.6-.1z"/>
<path class="st1" d="M73.3 62.8c3.1 0 6.1 1.2 8.3 3.4.3.3.7.5 1.2.5.4 0 .9-.2 1.2-.5 4.6-4.5 12-4.5 16.6.1 4.5 4.6 4.5 12-.1 16.6-.5.5-1.1 1-1.7 1.4l-15 12.2c-.3.2-.6.3-.9.3s-.7-.1-.9-.3L67 84.3c-1.4-.9-2.5-2-3.4-3.4-3-4.6-2.4-10.7 1.5-14.7 2.1-2.1 5.1-3.4 8.2-3.4m0-2c-3.6 0-7.1 1.4-9.7 4-4.6 4.6-5.3 11.8-1.8 17.2 1 1.6 2.3 2.9 3.9 3.9l15 12.1c1.3 1 3.1 1 4.3 0l14.9-12.1c6.3-4.2 8-12.7 3.8-19s-12.7-8-19-3.8c-.7.5-1.3 1-1.9 1.5-2.6-2.4-6-3.8-9.5-3.8z"/>
<path class="st3" d="M66.3 76.2h-.2c-1.1-.1-1.9-1-1.8-2.1.3-3.8 3.1-7 6.8-7.8 1-.4 2.2 0 2.6 1s0 2.2-1 2.6c-.2.1-.5.2-.8.2-2.1.5-3.6 2.2-3.8 4.3 0 1-.8 1.7-1.8 1.8z"/>
<path class="st1" d="M115.4 95.8c2.3 0 4.5.9 6.1 2.6.2.2.5.4.9.4.3 0 .6-.1.9-.4 3.4-3.4 8.9-3.4 12.3 0 3.4 3.4 3.4 8.9 0 12.3-.4.4-.8.8-1.3 1.1l-11.1 9c-.2.2-.4.2-.7.2-.2 0-.5-.1-.7-.2l-11.1-9c-1-.7-1.9-1.5-2.5-2.5-2.2-3.4-1.7-8 1.1-10.9 1.6-1.7 3.8-2.6 6.1-2.6m0-2c-2.8 0-5.5 1.1-7.5 3.1-3.6 3.6-4.1 9.2-1.4 13.4.8 1.2 1.8 2.2 3 3l11 8.9c1.1.9 2.7.9 3.9 0l11-9c4.9-3.3 6.1-10 2.8-14.8-3.3-4.9-10-6.1-14.8-2.8-.3.2-.7.5-1 .7-2-1.6-4.5-2.6-7-2.5z"/>
<path class="st3" d="M110.3 105.7c-.9-.1-1.5-.8-1.4-1.6.2-2.8 2.2-5.2 5-5.8.8-.2 1.6.3 1.8 1.1.2.8-.3 1.6-1.1 1.8h-.1c-1.5.3-2.7 1.6-2.8 3.2-.1.7-.7 1.3-1.4 1.3z"/>
</svg>

До

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

После

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

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

@ -50,7 +50,6 @@ caption {
}
groupbox {
font-size: 1em;
margin-top: 0;
margin-right: 4px;
margin-left: 4px;
@ -67,11 +66,6 @@ groupbox description {
margin-left: 0;
}
label.menu-text,
textbox.tree-input {
font-size: unset;
}
menulist label {
font-weight: unset;
}

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

@ -26,8 +26,6 @@
#mainPrefPane {
width: 100%;
padding: 0;
font: message-box;
color: currentColor;
}
prefpane > groupbox + groupbox {
@ -57,11 +55,15 @@ html|option {
description,
label {
line-height: 30px;
line-height: 1.8em;
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.tip-caption {
font-size: .9em;
}
menulist > hbox > label,
menuitem > label,
button > hbox > label {
@ -95,6 +97,24 @@ button > hbox > label {
margin: 4px 0;
}
.spotlight {
background-color: rgba(0,200,215,0.3);
/* Show the border to spotlight the components in high-contrast mode. */
border: 1px solid transparent;
border-radius: 2px;
}
[data-subcategory] {
margin-left: -4px;
margin-right: -4px;
padding-left: 4px;
padding-right: 4px;
}
[data-subcategory] > .groupbox-title {
padding-inline-start: 4px;
}
#searchInput {
border-radius: 0;
}
@ -211,12 +231,10 @@ button > hbox > label {
}
#updateApp > .groupbox-body > label {
margin: 0 0 4px 0;
line-height: 30px;
margin: 0 0 4px;
}
#updateApp > .groupbox-body > description {
line-height: 30px;
margin: 0;
}
@ -246,7 +264,7 @@ button > hbox > label {
}
#filter {
margin: 4px 0 8px 0;
margin: 4px 0 8px;
}
#handlersView {
@ -290,7 +308,7 @@ button > hbox > label {
/* Search Pane */
#engineList {
margin: 2px 0 5px 0;
margin: 2px 0 5px;
}
#engineList > treechildren::-moz-tree-image(engineShown, checked),
@ -319,7 +337,7 @@ button > hbox > label {
}
#addEnginesBox {
margin: 4px 0 0 0;
margin: 4px 0 0;
}
/* Privacy Pane */
@ -412,7 +430,6 @@ button > hbox > label {
background-color: #fbfbfb;
background-clip: content-box;
color: #424e5a;
font-size: 14px;
/* `transparent` will use the dialogText color in high-contrast themes and
when page colors are disabled */
border: 1px solid transparent;
@ -438,7 +455,7 @@ button > hbox > label {
}
.dialogTitle {
font-size: unset;
font-size: .9em;
text-align: center;
-moz-user-select: none;
}
@ -683,7 +700,7 @@ button > hbox > label {
.help-label {
margin: 0 4px;
line-height: 22px;
font-size: .9em;
-moz-user-select: none;
}
@ -725,9 +742,14 @@ button > hbox > label {
.search-container {
position: sticky;
background-color: var(--in-content-page-background);
width: 100%;
top: 0;
z-index: 1;
/* The search-container should have the capability to cover all spotlight area. */
width: calc(100% + 8px);
margin-left: -4px;
margin-right: -4px;
padding-left: 4px;
padding-right: 4px;
}
#searchInput {

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

@ -231,6 +231,7 @@ body {
.deck .instructions {
text-align: center;
color: rgba(12, 12, 13, .5);
padding: 0 11px;
max-width: 15em;
margin: 1em auto;

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

@ -4,10 +4,6 @@
%include ../../../shared/incontentprefs/dialog.inc.css
label,
textbox,
description,
.tab-text,
menulist label {
font-size: 1.25rem;
:root > * {
font-size: 1.12em;
}

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

@ -4,19 +4,8 @@
%include ../../../shared/incontentprefs/preferences.inc.css
html *,
page *,
window * {
font-size: 1.25rem;
}
caption label {
font-size: 1.42rem;
}
.tip-caption,
.help-label {
font-size: 1.08rem;
:root > * {
font-size: 1.25em;
}
.actionsMenu > .menulist-label-box > .menulist-icon {

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

@ -46,7 +46,6 @@ MACH_MODULES = [
'python/mozbuild/mozbuild/backend/mach_commands.py',
'python/mozbuild/mozbuild/compilation/codecomplete.py',
'python/mozbuild/mozbuild/frontend/mach_commands.py',
'services/common/tests/mach_commands.py',
'taskcluster/mach_commands.py',
'testing/awsy/mach_commands.py',
'testing/firefox-ui/mach_commands.py',

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

@ -219,15 +219,16 @@ button {
align-items: center;
margin-top: 1em;
margin-bottom: 1em;
background-image: url(chrome://devtools/skin/images/help.svg);
background-repeat: no-repeat;
background-size: 24px;
padding-inline-start: 32px;
height: 24px;
}
.addons-tip-icon {
margin-inline-end: 1ch;
width: 24px;
height: 24px;
background-image: url(chrome://devtools/skin/images/help.svg);
background-repeat: no-repeat;
background-size: 24px;
margin-inline-end: 8px;
}
.error-page {

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

@ -171,6 +171,7 @@ class AddonsPanel extends Component {
sort: true
}),
dom.div({ className: "addons-tip"},
dom.div({ className: "addons-tip-icon"}),
dom.span({
className: "addons-web-ext-tip",
}, Strings.GetStringFromName("webExtTip")),

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

@ -1,7 +1,7 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Taken from upstream commit: d2e91e574acbe3d5b546508d028bd278eaabd286
Taken from upstream commit: efa4ca367dadb1bb54525f9fe305dd38c0ec6323
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.0

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

@ -1758,6 +1758,11 @@ html .toggle-button-end.vertical svg {
.source-footer .blackbox-summary {
color: var(--theme-body-color);
}
.source-footer .mapped-source {
color: var(--theme-body-color);
padding: 2.5px;
}
/* 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/>. */

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -27467,66 +27467,8 @@ module.exports = function(module) {
/***/ }),
/* 794 */,
/* 795 */
/***/ (function(module, exports, __webpack_require__) {
var createToPairs = __webpack_require__(812),
keys = __webpack_require__(205);
/**
* Creates an array of own enumerable string keyed-value pairs for `object`
* which can be consumed by `_.fromPairs`. If `object` is a map or set, its
* entries are returned.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias entries
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the key-value pairs.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.toPairs(new Foo);
* // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
*/
var toPairs = createToPairs(keys);
module.exports = toPairs;
/***/ }),
/* 796 */
/***/ (function(module, exports, __webpack_require__) {
var arrayMap = __webpack_require__(110);
/**
* The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
* of key-value pairs for `object` corresponding to the property names of `props`.
*
* @private
* @param {Object} object The object to query.
* @param {Array} props The property names to get values for.
* @returns {Object} Returns the key-value pairs.
*/
function baseToPairs(object, props) {
return arrayMap(props, function(key) {
return [key, object[key]];
});
}
module.exports = baseToPairs;
/***/ }),
/* 795 */,
/* 796 */,
/* 797 */,
/* 798 */,
/* 799 */
@ -27711,7 +27653,7 @@ module.exports = matchesStrictComparable;
/* 812 */
/***/ (function(module, exports, __webpack_require__) {
var baseToPairs = __webpack_require__(796),
var baseToPairs = __webpack_require__(1757),
getTag = __webpack_require__(198),
mapToArray = __webpack_require__(203),
setToPairs = __webpack_require__(813);
@ -36616,7 +36558,7 @@ exports.getVariablesInLocalScope = getVariablesInLocalScope;
exports.getVariablesInScope = getVariablesInScope;
exports.isExpressionInScope = isExpressionInScope;
var _toPairs = __webpack_require__(795);
var _toPairs = __webpack_require__(1756);
var _toPairs2 = _interopRequireDefault(_toPairs);
@ -41822,6 +41764,118 @@ function extendsComponent(classes) {
return result;
}
/***/ }),
/* 1704 */,
/* 1705 */,
/* 1706 */,
/* 1707 */,
/* 1708 */,
/* 1709 */,
/* 1710 */,
/* 1711 */,
/* 1712 */,
/* 1713 */,
/* 1714 */,
/* 1715 */,
/* 1716 */,
/* 1717 */,
/* 1718 */,
/* 1719 */,
/* 1720 */,
/* 1721 */,
/* 1722 */,
/* 1723 */,
/* 1724 */,
/* 1725 */,
/* 1726 */,
/* 1727 */,
/* 1728 */,
/* 1729 */,
/* 1730 */,
/* 1731 */,
/* 1732 */,
/* 1733 */,
/* 1734 */,
/* 1735 */,
/* 1736 */,
/* 1737 */,
/* 1738 */,
/* 1739 */,
/* 1740 */,
/* 1741 */,
/* 1742 */,
/* 1743 */,
/* 1744 */,
/* 1745 */,
/* 1746 */,
/* 1747 */,
/* 1748 */,
/* 1749 */,
/* 1750 */,
/* 1751 */,
/* 1752 */,
/* 1753 */,
/* 1754 */,
/* 1755 */,
/* 1756 */
/***/ (function(module, exports, __webpack_require__) {
var createToPairs = __webpack_require__(812),
keys = __webpack_require__(205);
/**
* Creates an array of own enumerable string keyed-value pairs for `object`
* which can be consumed by `_.fromPairs`. If `object` is a map or set, its
* entries are returned.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias entries
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the key-value pairs.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.toPairs(new Foo);
* // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
*/
var toPairs = createToPairs(keys);
module.exports = toPairs;
/***/ }),
/* 1757 */
/***/ (function(module, exports, __webpack_require__) {
var arrayMap = __webpack_require__(110);
/**
* The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
* of key-value pairs for `object` corresponding to the property names of `props`.
*
* @private
* @param {Object} object The object to query.
* @param {Array} props The property names to get values for.
* @returns {Object} Returns the key-value pairs.
*/
function baseToPairs(object, props) {
return arrayMap(props, function(key) {
return [key, object[key]];
});
}
module.exports = baseToPairs;
/***/ })
/******/ ]);
});

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

@ -43,7 +43,7 @@ add_task(async function() {
assertPausedLocation(dbg);
// resume
await clickResume(dbg)
await clickResume(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);

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

@ -47,5 +47,8 @@ add_task(async function() {
await waitForLoadedSource(dbg, "long.js");
assertPausedLocation(dbg);
ok(isVisibleInEditor(dbg, findElement(dbg, "breakpoint")), "Breakpoint is visible");
ok(
isVisibleInEditor(dbg, findElement(dbg, "breakpoint")),
"Breakpoint is visible"
);
});

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

@ -47,7 +47,7 @@ async function editExpression(dbg, input) {
info("updating the expression");
dblClickElement(dbg, "expressionNode", 1);
// Position cursor reliably at the end of the text.
const evaluation = waitForDispatch(dbg, "EVALUATE_EXPRESSION")
const evaluation = waitForDispatch(dbg, "EVALUATE_EXPRESSION");
pressKey(dbg, "End");
type(dbg, input);
pressKey(dbg, "Enter");
@ -59,7 +59,7 @@ async function editExpression(dbg, input) {
* resume, and wait for the expression to finish being evaluated.
*/
async function addBadExpression(dbg, input) {
const evaluation = waitForDispatch(dbg, "EVALUATE_EXPRESSION")
const evaluation = waitForDispatch(dbg, "EVALUATE_EXPRESSION");
findElementWithSelector(dbg, expressionSelectors.input).focus();
type(dbg, input);
@ -70,7 +70,6 @@ async function addBadExpression(dbg, input) {
ok(dbg.selectors.isEvaluatingExpression(dbg.getState()));
await resume(dbg);
await evaluation;
}
add_task(async function() {

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

@ -32,8 +32,8 @@ add_task(async function() {
// The pretty-print button should go away in the pretty-printed
// source.
ok(!findElement(dbg, "editorFooter"), "Footer is hidden");
ok(!findElement(dbg, "prettyPrintButton"), "Pretty Print Button is hidden");
await selectSource(dbg, "math.min.js");
ok(findElement(dbg, "editorFooter"), "Footer is hidden");
ok(findElement(dbg, "prettyPrintButton"), "Pretty Print Button is visible");
});

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

@ -4,7 +4,11 @@
function assertBpInGutter(dbg, lineNumber) {
const el = findElement(dbg, "breakpoint");
const bpLineNumber = +el.querySelector(".CodeMirror-linenumber").innerText;
is(bpLineNumber, lineNumber, "Breakpoint is on the correct line in the gutter");
is(
bpLineNumber,
lineNumber,
"Breakpoint is on the correct line in the gutter"
);
}
// Tests loading sourcemapped sources, setting breakpoints, and
@ -38,4 +42,12 @@ add_task(async function() {
await waitForPaused(dbg);
assertPausedLocation(dbg);
// Tests the existence of the sourcemap link in the original source.
ok(findElement(dbg, "sourceMapLink"), "Sourcemap link in original source");
await selectSource(dbg, "main.min.js");
ok(
!findElement(dbg, "sourceMapLink"),
"No Sourcemap link exists in generated source"
);
});

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

@ -26,6 +26,7 @@ add_task(async function() {
await waitForPaused(dbg);
await waitForLoadedSource(dbg, "average.c");
assertPausedLocation(dbg);
toggleCallStack(dbg);
const frames = findAllElements(dbg, "frames");
const firstFrameTitle = frames[0].querySelector(".title").textContent;

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

@ -295,7 +295,9 @@ function assertDebugLine(dbg, line) {
const url = source.get("url");
ok(
false,
`Looks like the source ${url} is still loading. Try adding waitForLoadedSource in the test.`
`Looks like the source ${
url
} is still loading. Try adding waitForLoadedSource in the test.`
);
return;
}
@ -305,8 +307,9 @@ function assertDebugLine(dbg, line) {
"Line is highlighted as paused"
);
const debugLine = findElementWithSelector(dbg, ".new-debug-line")
|| findElementWithSelector(dbg, ".new-debug-line-error");
const debugLine =
findElementWithSelector(dbg, ".new-debug-line") ||
findElementWithSelector(dbg, ".new-debug-line-error");
ok(isVisibleInEditor(dbg, debugLine), "debug line is visible");
@ -553,8 +556,11 @@ function waitForLoadedSources(dbg) {
return waitForState(
dbg,
state => {
const sources = dbg.selectors.getSources(state).valueSeq().toJS()
return !sources.some(source => source.loadedState == "loading")
const sources = dbg.selectors
.getSources(state)
.valueSeq()
.toJS();
return !sources.some(source => source.loadedState == "loading");
},
"loaded source"
);
@ -835,7 +841,6 @@ function type(dbg, string) {
string.split("").forEach(char => EventUtils.synthesizeKey(char, {}, dbg.win));
}
/*
* Checks to see if the inner element is visible inside the editor.
*
@ -874,12 +879,14 @@ function isVisible(outerEl, innerEl) {
const outerRect = outerEl.getBoundingClientRect();
const verticallyVisible =
(innerRect.top >= outerRect.top || innerRect.bottom <= outerRect.bottom)
|| (innerRect.top < outerRect.top && innerRect.bottom > outerRect.bottom);
innerRect.top >= outerRect.top ||
innerRect.bottom <= outerRect.bottom ||
(innerRect.top < outerRect.top && innerRect.bottom > outerRect.bottom);
const horizontallyVisible =
(innerRect.left >= outerRect.left || innerRect.right <= outerRect.right)
|| (innerRect.left < outerRect.left && innerRect.right > outerRect.right);
innerRect.left >= outerRect.left ||
innerRect.right <= outerRect.right ||
(innerRect.left < outerRect.left && innerRect.right > outerRect.right);
const visible = verticallyVisible && horizontallyVisible;
return visible;
@ -891,7 +898,9 @@ const selectors = {
expressionNode: i =>
`.expressions-list .expression-container:nth-child(${i}) .object-label`,
expressionValue: i =>
`.expressions-list .expression-container:nth-child(${i}) .object-delimiter + *`,
`.expressions-list .expression-container:nth-child(${
i
}) .object-delimiter + *`,
expressionClose: i =>
`.expressions-list .expression-container:nth-child(${i}) .close`,
expressionNodes: ".expressions-list .tree-node",
@ -914,7 +923,8 @@ const selectors = {
stepOut: ".stepOut.active",
stepIn: ".stepIn.active",
toggleBreakpoints: ".breakpoints-toggle",
prettyPrintButton: ".prettyPrint",
prettyPrintButton: ".source-footer .prettyPrint",
sourceMapLink: ".source-footer .mapped-source",
sourcesFooter: ".sources-panel .source-footer",
editorFooter: ".editor-pane .source-footer",
sourceNode: i => `.sources-list .tree-node:nth-child(${i})`,

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

@ -0,0 +1,45 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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";
define(function (require, exports, module) {
const { Component } = require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
const { pre } = require("devtools/client/shared/vendor/react-dom-factories");
/**
* This object represents a live DOM text node in a <pre>.
*/
class LiveText extends Component {
static get propTypes() {
return {
data: PropTypes.instanceOf(Text),
};
}
componentDidMount() {
this.componentDidUpdate();
}
componentDidUpdate() {
let el = findDOMNode(this);
if (el.firstChild === this.props.data) {
return;
}
el.textContent = "";
el.append(this.props.data);
}
render() {
return pre({className: "data"});
}
}
// Exports from this module
exports.LiveText = LiveText;
});

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

@ -22,7 +22,7 @@ define(function (require, exports, module) {
class MainTabbedArea extends Component {
static get propTypes() {
return {
jsonText: PropTypes.string,
jsonText: PropTypes.instanceOf(Text),
tabActive: PropTypes.number,
actions: PropTypes.object,
headers: PropTypes.object,
@ -42,8 +42,8 @@ define(function (require, exports, module) {
super(props);
this.state = {
json: {},
headers: {},
json: props.json,
expandedNodes: props.expandedNodes,
jsonText: props.jsonText,
tabActive: props.tabActive
};
@ -64,7 +64,7 @@ define(function (require, exports, module) {
className: "json",
title: JSONView.Locale.$STR("jsonViewer.tab.JSON")},
JsonPanel({
data: this.props.json,
data: this.state.json,
expandedNodes: this.props.expandedNodes,
actions: this.props.actions,
searchFilter: this.state.searchFilter
@ -74,7 +74,8 @@ define(function (require, exports, module) {
className: "rawdata",
title: JSONView.Locale.$STR("jsonViewer.tab.RawData")},
TextPanel({
isValidJson: !(this.props.json instanceof Error),
isValidJson: !(this.state.json instanceof Error) &&
document.readyState != "loading",
data: this.state.jsonText,
actions: this.props.actions
})

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

@ -12,8 +12,8 @@ define(function (require, exports, module) {
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { createFactories } = require("devtools/client/shared/react-utils");
const { TextToolbar } = createFactories(require("./TextToolbar"));
const { div, pre } = dom;
const { LiveText } = createFactories(require("./LiveText"));
const { div } = dom;
/**
* This template represents the 'Raw Data' panel displaying
@ -24,7 +24,7 @@ define(function (require, exports, module) {
return {
isValidJson: PropTypes.bool,
actions: PropTypes.object,
data: PropTypes.string
data: PropTypes.instanceOf(Text),
};
}
@ -41,9 +41,7 @@ define(function (require, exports, module) {
isValidJson: this.props.isValidJson
}),
div({className: "panelContent"},
pre({className: "data"},
this.props.data
)
LiveText({data: this.props.data})
)
)
);

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

@ -14,6 +14,7 @@ DevToolsModules(
'HeadersToolbar.js',
'JsonPanel.js',
'JsonToolbar.js',
'LiveText.js',
'MainTabbedArea.js',
'SearchBox.js',
'TextPanel.js',

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

@ -168,6 +168,8 @@ function exportData(win, request) {
data.json = new win.Text();
data.readyState = "uninitialized";
let Locale = {
$STR: key => {
try {
@ -241,17 +243,16 @@ function initialHTML(doc) {
type: "text/css",
href: baseURI + "css/main.css",
}),
element("script", {
src: baseURI + "lib/require.js",
"data-main": baseURI + "viewer-config.js",
defer: true,
})
]),
element("body", {}, [
element("div", {"id": "content"}, [
element("div", {"id": "json"})
])
])
]),
element("script", {
src: baseURI + "lib/require.js",
"data-main": baseURI + "viewer-config.js",
}),
]),
]).outerHTML;
}

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

@ -19,41 +19,26 @@ define(function (require, exports, module) {
// Application state object.
let input = {
jsonText: JSONView.json.textContent,
jsonText: JSONView.json,
jsonPretty: null,
headers: JSONView.headers,
tabActive: 0,
prettified: false
};
try {
input.json = JSON.parse(input.jsonText);
} catch (err) {
input.json = err;
}
// Expand the document by default if its size isn't bigger than 100KB.
if (!(input.json instanceof Error) && input.jsonText.length <= AUTO_EXPAND_MAX_SIZE) {
input.expandedNodes = TreeViewClass.getExpandedNodes(
input.json,
{maxLevel: AUTO_EXPAND_MAX_LEVEL}
);
} else {
input.expandedNodes = new Set();
}
/**
* Application actions/commands. This list implements all commands
* available for the JSON viewer.
*/
input.actions = {
onCopyJson: function () {
copyString(input.prettified ? input.jsonPretty : input.jsonText);
let text = input.prettified ? input.jsonPretty : input.jsonText;
copyString(text.textContent);
},
onSaveJson: function () {
if (input.prettified && !prettyURL) {
prettyURL = URL.createObjectURL(new window.Blob([input.jsonPretty]));
prettyURL = URL.createObjectURL(new window.Blob([input.jsonPretty.textContent]));
}
dispatchEvent("save", input.prettified ? prettyURL : null);
},
@ -93,7 +78,7 @@ define(function (require, exports, module) {
theApp.setState({jsonText: input.jsonText});
} else {
if (!input.jsonPretty) {
input.jsonPretty = JSON.stringify(input.json, null, " ");
input.jsonPretty = new Text(JSON.stringify(input.json, null, " "));
}
theApp.setState({jsonText: input.jsonPretty});
}
@ -139,11 +124,52 @@ define(function (require, exports, module) {
* at the top of the window. This component also represents ReacJS root.
*/
let content = document.getElementById("content");
let promise = (async function parseJSON() {
if (document.readyState == "loading") {
// If the JSON has not been loaded yet, render the Raw Data tab first.
input.json = {};
input.expandedNodes = new Set();
input.tabActive = 1;
return new Promise(resolve => {
document.addEventListener("DOMContentLoaded", resolve, {once: true});
}).then(parseJSON).then(() => {
// Now update the state and switch to the JSON tab.
theApp.setState({
tabActive: 0,
json: input.json,
expandedNodes: input.expandedNodes,
});
});
}
// If the JSON has been loaded, parse it immediately before loading the app.
let jsonString = input.jsonText.textContent;
try {
input.json = JSON.parse(jsonString);
} catch (err) {
input.json = err;
}
// Expand the document by default if its size isn't bigger than 100KB.
if (!(input.json instanceof Error) && jsonString.length <= AUTO_EXPAND_MAX_SIZE) {
input.expandedNodes = TreeViewClass.getExpandedNodes(
input.json,
{maxLevel: AUTO_EXPAND_MAX_LEVEL}
);
}
return undefined;
})();
let theApp = render(MainTabbedArea(input), content);
// Send notification event to the window. Can be useful for
// Send readyState change notification event to the window. Can be useful for
// tests as well as extensions.
let event = new CustomEvent("JSONViewInitialized", {});
JSONView.initialized = true;
window.dispatchEvent(event);
JSONView.readyState = "interactive";
window.dispatchEvent(new CustomEvent("AppReadyStateChange"));
promise.then(() => {
// Another readyState change notification event.
JSONView.readyState = "complete";
window.dispatchEvent(new CustomEvent("AppReadyStateChange"));
});
});

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

@ -22,8 +22,11 @@ support-files =
!/devtools/client/framework/test/head.js
!/devtools/client/framework/test/shared-head.js
[browser_json_refresh.js]
[browser_jsonview_bug_1380828.js]
[browser_jsonview_ignore_charset.js]
[browser_jsonview_chunked_json.js]
support-files =
chunked_json.sjs
[browser_jsonview_content_type.js]
[browser_jsonview_copy_headers.js]
subsuite = clipboard
@ -38,6 +41,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_jsonview_empty_object.js]
[browser_jsonview_encoding.js]
[browser_jsonview_filter.js]
[browser_jsonview_ignore_charset.js]
[browser_jsonview_invalid_json.js]
[browser_jsonview_manifest.js]
[browser_jsonview_nojs.js]
@ -47,8 +51,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_jsonview_save_json.js]
support-files =
!/toolkit/content/tests/browser/common/mockTransfer.js
[browser_jsonview_theme.js]
[browser_jsonview_slash.js]
[browser_jsonview_valid_json.js]
[browser_json_refresh.js]
[browser_jsonview_serviceworker.js]
[browser_jsonview_slash.js]
[browser_jsonview_theme.js]
[browser_jsonview_valid_json.js]

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

@ -0,0 +1,84 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_JSON_URL = URL_ROOT + "chunked_json.sjs";
add_task(async function () {
info("Test chunked JSON started");
await addJsonViewTab(TEST_JSON_URL, {
appReadyState: "interactive",
docReadyState: "loading",
});
is(await getElementCount(".rawdata.is-active"), 1,
"The Raw Data tab is selected.");
// Write some text and check that it is displayed.
await write("[");
await checkText();
// Repeat just in case.
await write("1,");
await checkText();
is(await getElementCount("button.prettyprint"), 0,
"There is no pretty print button during load");
await selectJsonViewContentTab("json");
is(await getElementText(".jsonPanelBox > .panelContent"), "", "There is no JSON tree");
await selectJsonViewContentTab("headers");
ok(await getElementText(".headersPanelBox .netInfoHeadersTable"),
"The headers table has been filled.");
// Write some text without being in Raw Data, then switch tab and check.
await write("2");
await selectJsonViewContentTab("rawdata");
await checkText();
// Another text check.
await write("]");
await checkText();
// Close the connection.
let appReady = waitForContentMessage("Test:JsonView:AppReadyStateChange");
await server("close");
await appReady;
is(await getElementCount(".json.is-active"), 1, "The JSON tab is selected.");
is(await getElementCount(".jsonPanelBox .treeTable .treeRow"), 2,
"There is a tree with 2 rows.");
await selectJsonViewContentTab("rawdata");
await checkText();
is(await getElementCount("button.prettyprint"), 1, "There is a pretty print button.");
await clickJsonNode("button.prettyprint");
await checkText(JSON.stringify(JSON.parse(data), null, 2));
});
let data = " ";
async function write(text) {
data += text;
let dataReceived = waitForContentMessage("Test:JsonView:NewDataReceived");
await server("write", text);
await dataReceived;
}
async function checkText(text = data) {
is(await getElementText(".textPanelBox .data"), text, "Got the right text.");
}
function server(action, value) {
return new Promise(resolve => {
let xhr = new XMLHttpRequest();
xhr.open("GET", TEST_JSON_URL + "?" + action + "=" + value);
xhr.addEventListener("load", resolve, {once: true});
xhr.send();
});
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше