Merge autoland to mozilla-central. a=merge

This commit is contained in:
Daniel Varga 2019-04-11 00:51:52 +03:00
Родитель 6d6f6dadce 850323eece
Коммит f2b514eaaa
274 изменённых файлов: 3797 добавлений и 2608 удалений

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

@ -7,7 +7,7 @@
#include "Platform.h"
#include "nsIAccessibleEvent.h"
#include "nsIGConfService.h"
#include "nsIGSettingsService.h"
#include "nsIServiceManager.h"
#include "nsMai.h"
#include "AtkSocketAccessible.h"
@ -308,13 +308,21 @@ dbus_done:
if (dbusSuccess) return sShouldEnable;
#endif
// check gconf-2 setting
#define GCONF_A11Y_KEY "/desktop/gnome/interface/accessibility"
nsresult rv = NS_OK;
nsCOMPtr<nsIGConfService> gconf =
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && gconf)
gconf->GetBool(NS_LITERAL_CSTRING(GCONF_A11Y_KEY), &sShouldEnable);
// check GSettings
#define GSETINGS_A11Y_INTERFACE "org.gnome.desktop.interface"
#define GSETINGS_A11Y_KEY "toolkit-accessibility"
nsCOMPtr<nsIGSettingsService> gsettings =
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
nsCOMPtr<nsIGSettingsCollection> a11y_settings;
if (gsettings) {
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(GSETINGS_A11Y_INTERFACE),
getter_AddRefs(a11y_settings));
if (a11y_settings) {
a11y_settings->GetBoolean(NS_LITERAL_CSTRING(GSETINGS_A11Y_KEY),
&sShouldEnable);
}
}
return sShouldEnable;
}

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

@ -80,8 +80,8 @@ var gTabsPanel = {
menuitem.setAttribute("usercontextid", identity.userContextId);
// The command handler depends on this.
menuitem.setAttribute("data-usercontextid", identity.userContextId);
menuitem.setAttribute("data-identity-color", identity.color);
menuitem.setAttribute("data-identity-icon", identity.icon);
menuitem.classList.add("identity-icon-" + identity.icon);
menuitem.classList.add("identity-color-" + identity.color);
menuitem.setAttribute("command", "Browser:NewUserContextTab");

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

@ -57,7 +57,7 @@ var gDataNotificationInfoBar = {
popup: null,
callback: () => {
this._actionTaken = true;
window.openPreferences("privacy-reports", {origin: "dataReporting"});
window.openPreferences("privacy-reports");
},
}];

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

@ -155,7 +155,7 @@ var gEMEHandler = {
label: gNavigatorBundle.getString(btnLabelId),
accessKey: gNavigatorBundle.getString(btnAccessKeyId),
callback() {
openPreferences("general-drm", {origin: "browserMedia"});
openPreferences("general-drm");
},
dismiss: true,
};

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

@ -178,7 +178,7 @@
<menuitem id="menu_preferences"
label="&preferencesCmdUnix.label;"
accesskey="&preferencesCmdUnix.accesskey;"
oncommand="openPreferences(undefined, {origin: 'menubar'});"/>
oncommand="openPreferences(undefined);"/>
#endif
#endif
</menupopup>
@ -518,7 +518,7 @@
<menuitem id="menu_preferences"
label="&preferencesCmd2.label;"
accesskey="&preferencesCmd2.accesskey;"
oncommand="openPreferences(undefined, {origin: 'menubar'});"/>
oncommand="openPreferences(undefined);"/>
#endif
#ifdef MOZ_DEBUG
<menuitem id="menu_layout_debugger"
@ -529,7 +529,7 @@
#endif
#ifdef XP_MACOSX
<!-- nsMenuBarX hides these and uses them to build the Application menu. -->
<menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences(undefined, {origin: 'commandLineLegacy'});"/>
<menuitem id="menu_preferences" label="&preferencesCmdMac.label;" key="key_preferencesCmdMac" oncommand="openPreferences(undefined);"/>
<menuitem id="menu_mac_services" label="&servicesMenuMac.label;"/>
<menuitem id="menu_mac_hide_app" label="&hideThisAppCmdMac2.label;" key="key_hideThisAppCmdMac"/>
<menuitem id="menu_mac_hide_others" label="&hideOtherAppsCmdMac.label;" key="key_hideOtherAppsCmdMac"/>

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

@ -84,8 +84,7 @@
<command id="Browser:OpenLocation" oncommand="openLocation();"/>
<command id="Browser:RestoreLastSession" oncommand="SessionStore.restoreLastSession();" disabled="true"/>
<command id="Browser:NewUserContextTab" oncommand="openNewUserContextTab(event.sourceEvent);"/>
<command id="Browser:OpenAboutContainers" oncommand="openPreferences('paneContainers', {origin: 'ContainersCommand'});"/>
<command id="Browser:OpenAboutContainers" oncommand="openPreferences('paneContainers');"/>
<command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>
<command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>

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

@ -267,7 +267,7 @@ var gIdentityHandler = {
},
openPermissionPreferences() {
openPreferences("privacy-permissions", { origin: "identityPopup-permissions-PreferencesButton" });
openPreferences("privacy-permissions");
},
recordClick(object) {

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

@ -733,7 +733,7 @@ const gStoragePressureObserver = {
callback(notificationBar, button) {
// The advanced subpanes are only supported in the old organization, which will
// be removed by bug 1349689.
openPreferences("privacy-sitedata", { origin: "storagePressure" });
openPreferences("privacy-sitedata");
},
});
}
@ -4711,29 +4711,44 @@ function updateFileMenuUserContextUIVisibility(id) {
* Updates the User Context UI indicators if the browser is in a non-default context
*/
function updateUserContextUIIndicator() {
function replaceContainerClass(classType, element, value) {
let prefix = "identity-" + classType + "-";
if (value && element.classList.contains(prefix + value)) {
return;
}
for (let className of element.classList) {
if (className.startsWith(prefix)) {
element.classList.remove(className);
}
}
if (value) {
element.classList.add(prefix + value);
}
}
let hbox = document.getElementById("userContext-icons");
let userContextId = gBrowser.selectedBrowser.getAttribute("usercontextid");
if (!userContextId) {
hbox.setAttribute("data-identity-color", "");
replaceContainerClass("color", hbox, "");
hbox.hidden = true;
return;
}
let identity = ContextualIdentityService.getPublicIdentityFromId(userContextId);
if (!identity) {
hbox.setAttribute("data-identity-color", "");
replaceContainerClass("color", hbox, "");
hbox.hidden = true;
return;
}
hbox.setAttribute("data-identity-color", identity.color);
replaceContainerClass("color", hbox, identity.color);
let label = document.getElementById("userContext-label");
label.setAttribute("value", ContextualIdentityService.getUserContextLabel(userContextId));
let indicator = document.getElementById("userContext-indicator");
indicator.setAttribute("data-identity-icon", identity.icon);
replaceContainerClass("icon", indicator, identity.icon);
hbox.hidden = false;
}
@ -6952,7 +6967,7 @@ var OfflineApps = {
},
manage() {
openPreferences("panePrivacy", { origin: "offlineApps" });
openPreferences("panePrivacy");
},
receiveMessage(msg) {

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

@ -1338,7 +1338,9 @@
</vbox>
<vbox id="browser-border-end" hidden="true" layer="true"/>
</hbox>
<box id="customization-container" flex="1" hidden="true"><![CDATA[
#include ../../components/customizableui/content/customizeMode.inc.xul
]]></box>
</deck>
<html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true" renderroot="content">

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

@ -2355,7 +2355,7 @@ window._gBrowser = {
t.setAttribute("pinned", "true");
}
t.className = "tabbrowser-tab";
t.classList.add("tabbrowser-tab");
this.tabContainer._unlockTabSizing();

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

@ -1881,7 +1881,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
value="&urlbar.searchSuggestionsNotification.changeSettingsUnix;"
accesskey="&urlbar.searchSuggestionsNotification.changeSettingsUnix.accesskey;"
#endif
onclick="openPreferences('paneSearch', {origin: 'searchChangeSettings'});"
onclick="openPreferences('paneSearch');"
control="search-suggestions-change-settings"/>
</xul:hbox>
</xul:deck>

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

@ -28,25 +28,14 @@ Object.defineProperty(this, "BROWSER_NEW_TAB_URL", {
!aboutNewTabService.overridden) {
return "about:privatebrowsing";
}
// If the extension does not have private browsing permission,
// use about:privatebrowsing.
let extensionInfo;
try {
extensionInfo = ExtensionSettingsStore.getSetting("url_overrides", "newTabURL");
} catch (e) {
// ExtensionSettings may not be initialized if no extensions are enabled. If
// we have some indication that an extension controls the homepage, return
// the defaults instead.
if (aboutNewTabService.newTabURL.startsWith("moz-extension://")) {
return "about:privatebrowsing";
}
}
if (extensionInfo) {
let policy = WebExtensionPolicy.getByID(extensionInfo.id);
if (!policy || !policy.privateBrowsingAllowed) {
return "about:privatebrowsing";
}
// If an extension controls the setting and does not have private
// browsing permission, use the default setting.
let extensionControlled = Services.prefs.getBoolPref("browser.newtab.extensionControlled", false);
let privateAllowed = Services.prefs.getBoolPref("browser.newtab.privateAllowed", false);
// There is a potential on upgrade that the prefs are not set yet, so we double check
// for moz-extension.
if (!privateAllowed && (extensionControlled || aboutNewTabService.newTabURL.startsWith("moz-extension://"))) {
return "about:privatebrowsing";
}
}
return aboutNewTabService.newTabURL;
@ -682,13 +671,13 @@ function createUserContextMenu(event, {
}
menuitem.classList.add("menuitem-iconic");
menuitem.setAttribute("data-identity-color", identity.color);
menuitem.classList.add("identity-color-" + identity.color);
if (!isContextMenu) {
menuitem.setAttribute("command", "Browser:NewUserContextTab");
}
menuitem.setAttribute("data-identity-icon", identity.icon);
menuitem.classList.add("identity-icon-" + identity.icon);
docfrag.appendChild(menuitem);
});
@ -844,13 +833,6 @@ function openAboutDialog() {
}
function openPreferences(paneID, extraArgs) {
let histogram = Services.telemetry.getHistogramById("FX_PREFERENCES_OPENED_VIA");
if (extraArgs && extraArgs.origin) {
histogram.add(extraArgs.origin);
} else {
histogram.add("other");
}
// This function is duplicated from preferences.js.
function internalPrefCategoryNameToFriendlyName(aName) {
return (aName || "").replace(/^pane./, function(toReplace) { return toReplace[4].toLowerCase(); });

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

@ -304,11 +304,6 @@ function openBrowserWindow(cmdLine, triggeringPrincipal, urlOrUrlList, postData
}
function openPreferences(cmdLine, extraArgs) {
if (extraArgs && extraArgs.origin) {
Services.telemetry.getHistogramById("FX_PREFERENCES_OPENED_VIA").add(extraArgs.origin);
} else {
Services.telemetry.getHistogramById("FX_PREFERENCES_OPENED_VIA").add("other");
}
openBrowserWindow(cmdLine, gSystemPrincipal, "about:preferences");
}
@ -386,7 +381,7 @@ nsBrowserContentHandler.prototype = {
// Handle old preference dialog URLs.
if (chromeParam == "chrome://browser/content/pref/pref.xul" ||
chromeParam == "chrome://browser/content/preferences/preferences.xul") {
openPreferences(cmdLine, {origin: "commandLineLegacy"});
openPreferences(cmdLine);
cmdLine.preventDefault = true;
} else {
try {
@ -418,7 +413,7 @@ nsBrowserContentHandler.prototype = {
}
}
if (cmdLine.handleFlag("preferences", false)) {
openPreferences(cmdLine, {origin: "commandLineLegacy"});
openPreferences(cmdLine);
cmdLine.preventDefault = true;
}
if (cmdLine.handleFlag("silent", false))

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

@ -718,7 +718,7 @@ BrowserGlue.prototype = {
observe: async function BG_observe(subject, topic, data) {
switch (topic) {
case "notifications-open-settings":
this._openPreferences("privacy-permissions", { origin: "notifOpenSettings" });
this._openPreferences("privacy-permissions");
break;
case "final-ui-startup":
this._beforeUIStartup();
@ -2191,7 +2191,7 @@ BrowserGlue.prototype = {
let clickCallback = (subject, topic, data) => {
if (topic != "alertclickcallback")
return;
this._openPreferences("sync", { origin: "doorhanger" });
this._openPreferences("sync");
};
this.AlertsService.showAlertNotification(null, title, body, true, null, clickCallback);
},
@ -2869,7 +2869,7 @@ BrowserGlue.prototype = {
let clickCallback = (subject, topic, data) => {
if (topic != "alertclickcallback")
return;
this._openPreferences("sync", { origin: "devDisconnectedAlert"});
this._openPreferences("sync");
};
this.AlertsService.showAlertNotification(null, title, body, true, null, clickCallback);
},

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

@ -1,88 +1,88 @@
[data-identity-color="blue"] {
.identity-color-blue {
--identity-tab-color: #37adff;
--identity-icon-color: #37adff;
}
[data-identity-color="turquoise"] {
.identity-color-turquoise {
--identity-tab-color: #00c79a;
--identity-icon-color: #00c79a;
}
[data-identity-color="green"] {
.identity-color-green {
--identity-tab-color: #51cd00;
--identity-icon-color: #51cd00;
}
[data-identity-color="yellow"] {
.identity-color-yellow {
--identity-tab-color: #ffcb00;
--identity-icon-color: #ffcb00;
}
[data-identity-color="orange"] {
.identity-color-orange {
--identity-tab-color: #ff9f00;
--identity-icon-color: #ff9f00;
}
[data-identity-color="red"] {
.identity-color-red {
--identity-tab-color: #ff613d;
--identity-icon-color: #ff613d;
}
[data-identity-color="pink"] {
.identity-color-pink {
--identity-tab-color: #ff4bda;
--identity-icon-color: #ff4bda;
}
[data-identity-color="purple"] {
.identity-color-purple {
--identity-tab-color: #af51f5;
--identity-icon-color: #af51f5;
}
[data-identity-icon="fingerprint"] {
.identity-icon-fingerprint {
--identity-icon: url("resource://usercontext-content/fingerprint.svg");
}
[data-identity-icon="briefcase"] {
.identity-icon-briefcase {
--identity-icon: url("resource://usercontext-content/briefcase.svg");
}
[data-identity-icon="dollar"] {
.identity-icon-dollar {
--identity-icon: url("resource://usercontext-content/dollar.svg");
}
[data-identity-icon="cart"] {
.identity-icon-cart {
--identity-icon: url("resource://usercontext-content/cart.svg");
}
[data-identity-icon="circle"] {
.identity-icon-circle {
--identity-icon: url("resource://usercontext-content/circle.svg");
}
[data-identity-icon="vacation"] {
.identity-icon-vacation {
--identity-icon: url("resource://usercontext-content/vacation.svg");
}
[data-identity-icon="gift"] {
.identity-icon-gift {
--identity-icon: url("resource://usercontext-content/gift.svg");
}
[data-identity-icon="food"] {
.identity-icon-food {
--identity-icon: url("resource://usercontext-content/food.svg");
}
[data-identity-icon="fruit"] {
.identity-icon-fruit {
--identity-icon: url("resource://usercontext-content/fruit.svg");
}
[data-identity-icon="pet"] {
.identity-icon-pet {
--identity-icon: url("resource://usercontext-content/pet.svg");
}
[data-identity-icon="tree"] {
.identity-icon-tree {
--identity-icon: url("resource://usercontext-content/tree.svg");
}
[data-identity-icon="chill"] {
.identity-icon-chill {
--identity-icon: url("resource://usercontext-content/chill.svg");
}

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

@ -740,7 +740,7 @@ let preferencesButton = {
id: "preferences-button",
onCommand(aEvent) {
let win = aEvent.target.ownerGlobal;
win.openPreferences(undefined, {origin: "preferencesButton"});
win.openPreferences(undefined);
},
};
if (AppConstants.platform == "win") {

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

@ -100,6 +100,12 @@ function CustomizeMode(aWindow) {
this.browser = aWindow.gBrowser;
this.areas = new Set();
let content = this.$("customization-content-container");
if (!content) {
this.window.MozXULElement.insertFTLIfNeeded("browser/customizeMode.ftl");
let container = this.$("customization-container");
container.replaceChild(this.window.MozXULElement.parseXULToFragment(container.firstChild.data), container.lastChild);
}
// There are two palettes - there's the palette that can be overlayed with
// toolbar items in browser.xul. This is invisible, and never seen by the
// user. Then there's the visible palette, which gets populated and displayed

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

@ -2,139 +2,126 @@
- 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/. -->
<box id="customization-container" flex="1" hidden="true">
<box id="customization-content-container">
<box flex="1" id="customization-palette-container">
<label id="customization-header">
&customizeMode.menuAndToolbars.header3;
</label>
<vbox id="customization-palette" class="customization-palette" hidden="true"/>
<vbox id="customization-pong-arena" hidden="true"/>
<spacer id="customization-spacer"/>
<box id="customization-content-container">
<box flex="1" id="customization-palette-container">
<label id="customization-header" data-l10n-id="customize-mode-menu-and-toolbars-header"></label>
<vbox id="customization-palette" class="customization-palette" hidden="true"/>
<vbox id="customization-pong-arena" hidden="true"/>
<spacer id="customization-spacer"/>
</box>
<vbox id="customization-panel-container">
<vbox id="customization-panelWrapper">
<box class="panel-arrowbox">
<image class="panel-arrow" side="top"/>
</box>
<vbox id="customization-panel-container">
<vbox id="customization-panelWrapper">
<box class="panel-arrowbox">
<image class="panel-arrow" side="top"/>
</box>
<box class="panel-arrowcontent" side="top" flex="1">
<vbox id="customization-panelHolder">
<description id="customization-panelHeader">&customizeMode.overflowList.title2;</description>
<description id="customization-panelDescription">&customizeMode.overflowList.description;</description>
</vbox>
<box class="panel-inner-arrowcontentfooter" hidden="true"/>
</box>
<box class="panel-arrowcontent" side="top" flex="1">
<vbox id="customization-panelHolder">
<description id="customization-panelHeader" data-l10n-id="customize-mode-overflow-list-title"></description>
<description id="customization-panelDescription" data-l10n-id="customize-mode-overflow-list-description"></description>
</vbox>
</vbox>
</box>
<hbox id="customization-footer">
<checkbox id="customization-titlebar-visibility-checkbox" class="customizationmode-checkbox"
label="&customizeMode.titlebar;"
<box class="panel-inner-arrowcontentfooter" hidden="true"/>
</box>
</vbox>
</vbox>
</box>
<hbox id="customization-footer">
<checkbox id="customization-titlebar-visibility-checkbox" class="customizationmode-checkbox"
# NB: because oncommand fires after click, by the time we've fired, the checkbox binding
# will already have switched the button's state, so this is correct:
oncommand="gCustomizeMode.toggleTitlebar(this.checked)"/>
<checkbox id="customization-extra-drag-space-checkbox" class="customizationmode-checkbox"
label="&customizeMode.extraDragSpace;"
oncommand="gCustomizeMode.toggleDragSpace(this.checked)"/>
<button id="customization-toolbar-visibility-button" label="&customizeMode.toolbars2;" class="customizationmode-button" type="menu">
<menupopup id="customization-toolbar-menu" onpopupshowing="onViewToolbarsPopupShowing(event)"/>
</button>
<button id="customization-lwtheme-button" label="&customizeMode.lwthemes;" class="customizationmode-button" type="menu">
<panel type="arrow" id="customization-lwtheme-menu"
onpopupshowing="gCustomizeMode.onThemesMenuShowing(event);"
position="topcenter bottomleft"
flip="none"
role="menu">
<label id="customization-lwtheme-menu-header" value="&customizeMode.lwthemes.myThemes;"/>
<hbox id="customization-lwtheme-menu-footer">
<toolbarbutton class="customization-lwtheme-menu-footeritem"
label="&customizeMode.lwthemes.menuManage;"
accesskey="&customizeMode.lwthemes.menuManage.accessKey;"
tabindex="0"
oncommand="gCustomizeMode.openAddonsManagerThemes(event);"/>
<toolbarbutton class="customization-lwtheme-menu-footeritem"
label="&customizeMode.lwthemes.menuGetMore;"
accesskey="&customizeMode.lwthemes.menuGetMore.accessKey;"
tabindex="0"
oncommand="gCustomizeMode.getMoreThemes(event);"/>
</hbox>
</panel>
</button>
<button id="customization-uidensity-button"
label="&customizeMode.uidensity;"
class="customizationmode-button"
type="menu">
<panel type="arrow" id="customization-uidensity-menu"
onpopupshowing="gCustomizeMode.onUIDensityMenuShowing();"
position="topcenter bottomleft"
flip="none"
role="menu">
<menuitem id="customization-uidensity-menuitem-compact"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
label="&customizeMode.uidensity.menuCompact.label;"
accesskey="&customizeMode.uidensity.menuCompact.accessKey;"
tooltiptext="&customizeMode.uidensity.menuCompact.tooltip;"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);" />
<menuitem id="customization-uidensity-menuitem-normal"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
label="&customizeMode.uidensity.menuNormal.label;"
accesskey="&customizeMode.uidensity.menuNormal.accessKey;"
tooltiptext="&customizeMode.uidensity.menuNormal.tooltip;"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);" />
oncommand="gCustomizeMode.toggleTitlebar(this.checked)" data-l10n-id="customize-mode-titlebar"/>
<checkbox id="customization-extra-drag-space-checkbox" class="customizationmode-checkbox"
data-l10n-id="customize-mode-extra-drag-space"
oncommand="gCustomizeMode.toggleDragSpace(this.checked)"/>
<button id="customization-toolbar-visibility-button" class="customizationmode-button" type="menu" data-l10n-id="customize-mode-toolbars">
<menupopup id="customization-toolbar-menu" onpopupshowing="onViewToolbarsPopupShowing(event)"/>
</button>
<button id="customization-lwtheme-button" data-l10n-id="customize-mode-lwthemes" class="customizationmode-button" type="menu">
<panel type="arrow" id="customization-lwtheme-menu"
onpopupshowing="gCustomizeMode.onThemesMenuShowing(event);"
position="topcenter bottomleft"
flip="none"
role="menu">
<label id="customization-lwtheme-menu-header" data-l10n-id="customize-mode-lwthemes-my-themes"/>
<hbox id="customization-lwtheme-menu-footer">
<toolbarbutton class="customization-lwtheme-menu-footeritem"
data-l10n-id="customize-mode-lwthemes-menu-manage"
tabindex="0"
oncommand="gCustomizeMode.openAddonsManagerThemes(event);"/>
<toolbarbutton class="customization-lwtheme-menu-footeritem"
data-l10n-id="customize-mode-lwthemes-menu-get-more"
tabindex="0"
oncommand="gCustomizeMode.getMoreThemes(event);"/>
</hbox>
</panel>
</button>
<button id="customization-uidensity-button"
data-l10n-id="customize-mode-uidensity"
class="customizationmode-button"
type="menu">
<panel type="arrow" id="customization-uidensity-menu"
onpopupshowing="gCustomizeMode.onUIDensityMenuShowing();"
position="topcenter bottomleft"
flip="none"
role="menu">
<menuitem id="customization-uidensity-menuitem-compact"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
data-l10n-id="customize-mode-uidensity-menu-compact"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);"/>
<menuitem id="customization-uidensity-menuitem-normal"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
data-l10n-id="customize-mode-uidensity-menu-normal"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);"/>
#ifndef XP_MACOSX
<menuitem id="customization-uidensity-menuitem-touch"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
label="&customizeMode.uidensity.menuTouch.label;"
accesskey="&customizeMode.uidensity.menuTouch.accessKey;"
tooltiptext="&customizeMode.uidensity.menuTouch.tooltip;"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);">
</menuitem>
<spacer hidden="true" id="customization-uidensity-touch-spacer"/>
<checkbox id="customization-uidensity-autotouchmode-checkbox"
hidden="true"
label="&customizeMode.uidensity.autoTouchMode.checkbox.label;"
oncommand="gCustomizeMode.updateAutoTouchMode(this.checked)"/>
<menuitem id="customization-uidensity-menuitem-touch"
class="menuitem-iconic customization-uidensity-menuitem"
role="menuitemradio"
data-l10n-id="customize-mode-uidensity-menu-touch"
tabindex="0"
onfocus="gCustomizeMode.updateUIDensity(this.mode);"
onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
onblur="gCustomizeMode.resetUIDensity();"
onmouseout="gCustomizeMode.resetUIDensity();"
oncommand="gCustomizeMode.setUIDensity(this.mode);">
</menuitem>
<spacer hidden="true" id="customization-uidensity-touch-spacer"/>
<checkbox id="customization-uidensity-autotouchmode-checkbox"
hidden="true"
data-l10n-id="customize-mode-uidensity-auto-touch-mode-checkbox"
oncommand="gCustomizeMode.updateAutoTouchMode(this.checked)"/>
#endif
</panel>
</button>
</panel>
</button>
<button id="whimsy-button"
type="checkbox"
class="customizationmode-button"
oncommand="gCustomizeMode.togglePong(this.checked);"
hidden="true"/>
<button id="whimsy-button"
type="checkbox"
class="customizationmode-button"
oncommand="gCustomizeMode.togglePong(this.checked);"
hidden="true"/>
<spacer id="customization-footer-spacer"/>
<button id="customization-undo-reset-button"
class="customizationmode-button"
hidden="true"
oncommand="gCustomizeMode.undoReset();"
label="&undoCmd.label;"/>
<button id="customization-reset-button"
oncommand="gCustomizeMode.reset();"
label="&customizeMode.restoreDefaults;"
class="customizationmode-button"/>
<button id="customization-done-button"
oncommand="gCustomizeMode.exit();"
label="&customizeMode.done;"
class="customizationmode-button"/>
</hbox>
</box>
<spacer id="customization-footer-spacer"/>
<button id="customization-undo-reset-button"
class="customizationmode-button"
hidden="true"
oncommand="gCustomizeMode.undoReset();"
data-l10n-id="customize-mode-undo-cmd"/>
<button id="customization-reset-button"
oncommand="gCustomizeMode.reset();"
data-l10n-id="customize-mode-restore-defaults"
class="customizationmode-button"/>
<button id="customization-done-button"
oncommand="gCustomizeMode.exit();"
data-l10n-id="customize-mode-done"
class="customizationmode-button"/>
</hbox>

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

@ -897,6 +897,12 @@ var Policies = {
},
},
"SearchSuggestEnabled": {
onBeforeAddons(manager, param) {
setAndLockPref("browser.urlbar.suggest.searches", param);
},
},
"SecurityDevices": {
onProfileAfterChange(manager, param) {
let securityDevices = param;

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

@ -566,6 +566,15 @@
},
"browser.cache.disk.parent_directory": {
"type": "string"
},
"browser.urlbar.suggest.openpage": {
"type": "boolean"
},
"browser.urlbar.suggest.history": {
"type": "boolean"
},
"browser.urlbar.suggest.bookmark": {
"type": "boolean"
}
}
},
@ -696,6 +705,10 @@
}
},
"SearchSuggestEnabled": {
"type": "boolean"
},
"SecurityDevices": {
"type": "object",
"patternProperties": {

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

@ -278,6 +278,16 @@ const POLICIES_TESTS = [
"browser.newtabpage.enabled": false,
},
},
// POLICY: SearchSuggestEnabled
{
policies: {
"SearchSuggestEnabled": false,
},
lockedPrefs: {
"browser.urlbar.suggest.searches": false,
},
},
];
add_task(async function test_policy_remember_passwords() {

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

@ -5,6 +5,7 @@
"use strict";
var {ExtensionPreferencesManager} = ChromeUtils.import("resource://gre/modules/ExtensionPreferencesManager.jsm");
var {ExtensionParent} = ChromeUtils.import("resource://gre/modules/ExtensionParent.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
@ -16,6 +17,8 @@ const DEFAULT_SEARCH_SETTING_NAME = "defaultSearch";
const ENGINE_ADDED_SETTING_NAME = "engineAdded";
const HOMEPAGE_PREF = "browser.startup.homepage";
const HOMEPAGE_PRIVATE_ALLOWED = "browser.startup.homepage_override.privateAllowed";
const HOMEPAGE_EXTENSION_CONTROLLED = "browser.startup.homepage_override.extensionControlled";
const HOMEPAGE_CONFIRMED_TYPE = "homepageNotification";
const HOMEPAGE_SETTING_TYPE = "prefs";
const HOMEPAGE_SETTING_NAME = "homepage_override";
@ -186,12 +189,36 @@ this.chrome_settings_overrides = class extends ExtensionAPI {
// We need to add the listener here too since onPrefsChanged won't trigger on a
// restart (the prefs are already set).
if (inControl) {
Services.prefs.setBoolPref(HOMEPAGE_PRIVATE_ALLOWED, extension.privateBrowsingAllowed);
// Also set this now as an upgraded browser will need this.
Services.prefs.setBoolPref(HOMEPAGE_EXTENSION_CONTROLLED, true);
if (extension.startupReason == "APP_STARTUP") {
handleInitialHomepagePopup(extension.id, homepageUrl);
} else {
homepagePopup.addObserver(extension.id);
}
}
// We need to monitor permission change and update the preferences.
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("add-permissions", async (ignoreEvent, permissions) => {
if (permissions.permissions.includes("internal:privateBrowsingAllowed")) {
let item = await ExtensionPreferencesManager.getSetting("homepage_override");
if (item.id == extension.id) {
Services.prefs.setBoolPref(HOMEPAGE_PRIVATE_ALLOWED, true);
}
}
});
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("remove-permissions", async (ignoreEvent, permissions) => {
if (permissions.permissions.includes("internal:privateBrowsingAllowed")) {
let item = await ExtensionPreferencesManager.getSetting("homepage_override");
if (item.id == extension.id) {
Services.prefs.setBoolPref(HOMEPAGE_PRIVATE_ALLOWED, false);
}
}
});
extension.callOnClose({
close: () => {
if (extension.shutdownReason == "ADDON_DISABLE") {
@ -344,6 +371,7 @@ this.chrome_settings_overrides = class extends ExtensionAPI {
ExtensionPreferencesManager.addSetting("homepage_override", {
prefNames: [
HOMEPAGE_PREF,
HOMEPAGE_EXTENSION_CONTROLLED,
],
// ExtensionPreferencesManager will call onPrefsChanged when control changes
// and it updates the preferences. We are passed the item from
@ -353,13 +381,21 @@ ExtensionPreferencesManager.addSetting("homepage_override", {
onPrefsChanged(item) {
if (item.id) {
homepagePopup.addObserver(item.id);
let policy = ExtensionParent.WebExtensionPolicy.getByID(item.id);
Services.prefs.setBoolPref(HOMEPAGE_PRIVATE_ALLOWED, policy && policy.privateBrowsingAllowed);
Services.prefs.setBoolPref(HOMEPAGE_EXTENSION_CONTROLLED, true);
} else {
homepagePopup.removeObserver();
Services.prefs.clearUserPref(HOMEPAGE_PRIVATE_ALLOWED);
Services.prefs.clearUserPref(HOMEPAGE_EXTENSION_CONTROLLED);
}
},
setCallback(value) {
return {
[HOMEPAGE_PREF]: value,
[HOMEPAGE_EXTENSION_CONTROLLED]: !!value,
};
},
});

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

@ -4,6 +4,8 @@
"use strict";
var {ExtensionParent} = ChromeUtils.import("resource://gre/modules/ExtensionParent.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionControlledPopup",
"resource:///modules/ExtensionControlledPopup.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
@ -16,6 +18,8 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
const STORE_TYPE = "url_overrides";
const NEW_TAB_SETTING_NAME = "newTabURL";
const NEW_TAB_CONFIRMED_TYPE = "newTabNotification";
const NEW_TAB_PRIVATE_ALLOWED = "browser.newtab.privateAllowed";
const NEW_TAB_EXTENSION_CONTROLLED = "browser.newtab.extensionControlled";
XPCOMUtils.defineLazyGetter(this, "newTabPopup", () => {
return new ExtensionControlledPopup({
@ -60,12 +64,34 @@ XPCOMUtils.defineLazyGetter(this, "newTabPopup", () => {
function setNewTabURL(extensionId, url) {
if (extensionId) {
newTabPopup.addObserver(extensionId);
let policy = ExtensionParent.WebExtensionPolicy.getByID(extensionId);
Services.prefs.setBoolPref(NEW_TAB_PRIVATE_ALLOWED, policy && policy.privateBrowsingAllowed);
Services.prefs.setBoolPref(NEW_TAB_EXTENSION_CONTROLLED, true);
} else {
newTabPopup.removeObserver();
Services.prefs.clearUserPref(NEW_TAB_PRIVATE_ALLOWED);
Services.prefs.clearUserPref(NEW_TAB_EXTENSION_CONTROLLED);
}
if (url) {
aboutNewTabService.newTabURL = url;
}
aboutNewTabService.newTabURL = url;
}
// eslint-disable-next-line mozilla/balanced-listeners
ExtensionParent.apiManager.on("extension-setting-changed", async (eventName, setting) => {
let extensionId, url;
if (setting.type === STORE_TYPE && setting.key === NEW_TAB_SETTING_NAME) {
if (setting.action === "enable" || setting.item) {
let {item} = setting;
// If setting.item exists, it is the new value. If it doesn't exist, and an
// extension is being enabled, we use the id.
extensionId = (item && item.id) || setting.id;
url = item && (item.value || item.initialValue);
}
}
setNewTabURL(extensionId, url);
});
this.urlOverrides = class extends ExtensionAPI {
static onUninstall(id) {
// TODO: This can be removed once bug 1438364 is fixed and all data is cleaned up.
@ -74,10 +100,7 @@ this.urlOverrides = class extends ExtensionAPI {
processNewTabSetting(action) {
let {extension} = this;
let item = ExtensionSettingsStore[action](extension.id, STORE_TYPE, NEW_TAB_SETTING_NAME);
if (item) {
setNewTabURL(item.id, item.value || item.initialValue);
}
ExtensionSettingsStore[action](extension.id, STORE_TYPE, NEW_TAB_SETTING_NAME);
}
async onManifestEntry(entryName) {
@ -125,6 +148,26 @@ this.urlOverrides = class extends ExtensionAPI {
if (item) {
setNewTabURL(item.id, item.value || item.initialValue);
}
// We need to monitor permission change and update the preferences.
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("add-permissions", async (ignoreEvent, permissions) => {
if (permissions.permissions.includes("internal:privateBrowsingAllowed")) {
let item = await ExtensionSettingsStore.getSetting(STORE_TYPE, NEW_TAB_SETTING_NAME);
if (item && item.id == extension.id) {
Services.prefs.setBoolPref(NEW_TAB_PRIVATE_ALLOWED, true);
}
}
});
// eslint-disable-next-line mozilla/balanced-listeners
extension.on("remove-permissions", async (ignoreEvent, permissions) => {
if (permissions.permissions.includes("internal:privateBrowsingAllowed")) {
let item = await ExtensionSettingsStore.getSetting(STORE_TYPE, NEW_TAB_SETTING_NAME);
if (item && item.id == extension.id) {
Services.prefs.setBoolPref(NEW_TAB_PRIVATE_ALLOWED, false);
}
}
});
}
}
};

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

@ -8,3 +8,4 @@ support-files =
head.js
[browser_ext_tabs_cookieStoreId_private.js]
[browser_ext_tabs_newtab_private.js]

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

@ -0,0 +1,79 @@
"use strict";
const {GlobalManager} = ChromeUtils.import("resource://gre/modules/Extension.jsm", null);
const {ExtensionPermissions} = ChromeUtils.import("resource://gre/modules/ExtensionPermissions.jsm");
const NEWTAB_PRIVATE_ALLOWED = "browser.newtab.privateAllowed";
const NEWTAB_EXTENSION_CONTROLLED = "browser.newtab.extensionControlled";
const NEWTAB_URI = "webext-newtab-1.html";
function promisePrefChange(pref) {
return new Promise((resolve, reject) => {
Services.prefs.addObserver(pref, function observer() {
Services.prefs.removeObserver(pref, observer);
resolve(arguments);
});
});
}
function verifyPrefSettings(controlled, allowed) {
is(Services.prefs.getBoolPref(NEWTAB_EXTENSION_CONTROLLED, false), controlled, "newtab extension controlled");
is(Services.prefs.getBoolPref(NEWTAB_PRIVATE_ALLOWED, false), allowed, "newtab private permission after permission change");
if (controlled) {
ok(aboutNewTabService.newTabURL.endsWith(NEWTAB_URI), "Newtab url is overridden by the extension.");
}
if (controlled && allowed) {
ok(BROWSER_NEW_TAB_URL.endsWith(NEWTAB_URI), "active newtab url is overridden by the extension.");
} else {
let expectednewTab = controlled ? "about:privatebrowsing" : "about:newtab";
is(BROWSER_NEW_TAB_URL, expectednewTab, "active newtab url is default.");
}
}
async function promiseUpdatePrivatePermission(allowed, extension) {
info(`update private allowed permission`);
let ext = GlobalManager.extensionMap.get(extension.id);
await Promise.all([
promisePrefChange(NEWTAB_PRIVATE_ALLOWED),
ExtensionPermissions[allowed ? "add" : "remove"](extension.id,
{permissions: ["internal:privateBrowsingAllowed"], origins: []},
ext),
]);
verifyPrefSettings(true, allowed);
}
add_task(async function test_new_tab_private() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"applications": {
"gecko": {
"id": "@private-newtab",
},
},
"chrome_url_overrides": {
newtab: NEWTAB_URI,
},
},
files: {
NEWTAB_URI: `
<!DOCTYPE html>
<head>
<meta charset="utf-8"/></head>
<html>
<body>
</body>
</html>
`,
},
useAddonManager: "permanent",
});
await extension.startup();
verifyPrefSettings(true, false);
promiseUpdatePrivatePermission(true, extension);
await extension.unload();
});

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

@ -0,0 +1,117 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const {AddonTestUtils} = ChromeUtils.import("resource://testing-common/AddonTestUtils.jsm");
const {HomePage} = ChromeUtils.import("resource:///modules/HomePage.jsm");
const {ExtensionPermissions} = ChromeUtils.import("resource://gre/modules/ExtensionPermissions.jsm");
const {
createAppInfo,
promiseShutdownManager,
promiseStartupManager,
} = AddonTestUtils;
const EXTENSION_ID = "test_overrides@tests.mozilla.org";
const HOMEPAGE_EXTENSION_CONTROLLED = "browser.startup.homepage_override.extensionControlled";
const HOMEPAGE_PRIVATE_ALLOWED = "browser.startup.homepage_override.privateAllowed";
const HOMEPAGE_URL_PREF = "browser.startup.homepage";
const HOMEPAGE_URI = "webext-homepage-1.html";
Services.prefs.setBoolPref("browser.privatebrowsing.autostart", true);
Services.prefs.setBoolPref("extensions.allowPrivateBrowsingByDefault", false);
AddonTestUtils.init(this);
AddonTestUtils.usePrivilegedSignatures = false;
AddonTestUtils.overrideCertDB();
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
function promisePrefChange(pref) {
return new Promise((resolve, reject) => {
Services.prefs.addObserver(pref, function observer() {
Services.prefs.removeObserver(pref, observer);
resolve(arguments);
});
});
}
let defaultHomepageURL;
function verifyPrefSettings(controlled, allowed) {
equal(Services.prefs.getBoolPref(HOMEPAGE_EXTENSION_CONTROLLED, false), controlled, "homepage extension controlled");
equal(Services.prefs.getBoolPref(HOMEPAGE_PRIVATE_ALLOWED, false), allowed, "homepage private permission after permission change");
if (controlled && allowed) {
ok(HomePage.get().endsWith(HOMEPAGE_URI), "Home page url is overridden by the extension");
} else {
equal(HomePage.get(), defaultHomepageURL, "Home page url is default.");
}
}
async function promiseUpdatePrivatePermission(allowed, extension) {
info(`update private allowed permission`);
await Promise.all([
promisePrefChange(HOMEPAGE_PRIVATE_ALLOWED),
ExtensionPermissions[allowed ? "add" : "remove"](extension.id,
{permissions: ["internal:privateBrowsingAllowed"], origins: []},
extension),
]);
verifyPrefSettings(true, allowed);
}
add_task(async function test_overrides_private() {
await promiseStartupManager();
let extensionInfo = {
useAddonManager: "permanent",
manifest: {
"version": "1.0",
"applications": {
"gecko": {
"id": EXTENSION_ID,
},
},
"chrome_settings_overrides": {
"homepage": HOMEPAGE_URI,
},
},
};
let extension = ExtensionTestUtils.loadExtension(extensionInfo);
defaultHomepageURL = HomePage.get();
await extension.startup();
verifyPrefSettings(true, false);
equal(HomePage.get(), defaultHomepageURL, "Home page url is default.");
info("add permission to extension");
await promiseUpdatePrivatePermission(true, extension.extension);
info("remove permission from extension");
await promiseUpdatePrivatePermission(false, extension.extension);
// set back to true to test upgrade removing extension control
info("add permission back to prepare for upgrade test");
await promiseUpdatePrivatePermission(true, extension.extension);
extensionInfo.manifest = {
"version": "2.0",
"applications": {
"gecko": {
"id": EXTENSION_ID,
},
},
};
await Promise.all([
promisePrefChange(HOMEPAGE_URL_PREF),
extension.upgrade(extensionInfo),
]);
verifyPrefSettings(false, false);
await extension.unload();
await promiseShutdownManager();
});

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

@ -12,4 +12,5 @@
[test_ext_settings_overrides_shutdown.js]
[test_ext_url_overrides_newtab.js]
[test_ext_url_overrides_newtab_update.js]
[test_ext_homepage_overrides_private.js]

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

@ -1063,7 +1063,7 @@ class _ASRouter {
target.browser.ownerGlobal.openTrustedLinkIn(`about:${action.data.args}`, "tab");
break;
case ra.OPEN_PREFERENCES_PAGE:
target.browser.ownerGlobal.openPreferences(action.data.category, {origin: action.data.origin});
target.browser.ownerGlobal.openPreferences(action.data.category);
break;
case ra.OPEN_APPLICATIONS_MENU:
UITour.showMenu(target.browser.ownerGlobal, action.data.args);

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

@ -95,7 +95,7 @@ this.AboutPreferences = class AboutPreferences {
this.uninit();
break;
case at.SETTINGS_OPEN:
action._target.browser.ownerGlobal.openPreferences("paneHome", {origin: "aboutHome"});
action._target.browser.ownerGlobal.openPreferences("paneHome");
break;
// This is used to open the web extension settings page for an extension
case at.OPEN_WEBEXT_SETTINGS:

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

@ -929,7 +929,7 @@ describe("ASRouter", () => {
await Router.onMessage(msg);
assert.calledOnce(msg.target.browser.ownerGlobal.openPreferences);
assert.calledWith(msg.target.browser.ownerGlobal.openPreferences, "something", {origin: "o"});
assert.calledWith(msg.target.browser.ownerGlobal.openPreferences, "something");
});
});

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

@ -106,7 +106,7 @@ let gContainersManager = {
document.l10n.setAttributes(iconSwatch, `containers-icon-${icon}`);
let iconElement = document.createXULElement("hbox");
iconElement.className = "userContext-icon";
iconElement.setAttribute("data-identity-icon", icon);
iconElement.classList.add("identity-icon-" + icon);
iconSwatch.appendChild(iconElement);
radiogroup.appendChild(iconSwatch);
@ -134,8 +134,8 @@ let gContainersManager = {
document.l10n.setAttributes(colorSwatch, `containers-color-${color}`);
let iconElement = document.createXULElement("hbox");
iconElement.className = "userContext-icon";
iconElement.setAttribute("data-identity-icon", "circle");
iconElement.setAttribute("data-identity-color", color);
iconElement.classList.add("identity-icon-circle");
iconElement.classList.add("identity-color-" + color);
colorSwatch.appendChild(iconElement);
radiogroup.appendChild(colorSwatch);

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

@ -40,8 +40,8 @@ let gContainersPane = {
userContextIcon.className = "userContext-icon";
userContextIcon.setAttribute("width", 24);
userContextIcon.setAttribute("height", 24);
userContextIcon.setAttribute("data-identity-icon", container.icon);
userContextIcon.setAttribute("data-identity-color", container.color);
userContextIcon.classList.add("identity-icon-" + container.icon);
userContextIcon.classList.add("identity-color-" + container.color);
outer.appendChild(userContextIcon);
let label = document.createXULElement("label");

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

@ -1178,7 +1178,7 @@ class SearchOneOffs {
if (target == this.settingsButton ||
target == this.settingsButtonCompact) {
openPreferences("paneSearch", { origin: "contentSearch" });
openPreferences("paneSearch");
// If the preference tab was already selected, the panel doesn't
// close itself automatically.

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

@ -9,7 +9,6 @@ LOCAL_INCLUDES += [
'/xpcom/build'
]
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']

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

@ -70,31 +70,7 @@ add_task(async function() {
gsettings.setString(GS_OPTION_KEY, prevOption);
gsettings.setBoolean(GS_DRAW_BG_KEY, prevDrawBG);
};
} catch (e) {
// Fallback to GConf
var gconf = Cc["@mozilla.org/gnome-gconf-service;1"].
getService(Ci.nsIGConfService);
var prevImageKey = gconf.getString(DG_IMAGE_KEY);
var prevOptionKey = gconf.getString(DG_OPTION_KEY);
var prevDrawBgKey = gconf.getBool(DG_DRAW_BG_KEY);
checkWallpaper = function(position, expectedGConfPosition) {
shell.setDesktopBackground(image, position, "");
ok(wpFile.exists(), "Wallpaper was written to disk");
is(gconf.getString(DG_IMAGE_KEY), wpFile.path,
"Wallpaper file GConf key is correct");
is(gconf.getString(DG_OPTION_KEY), expectedGConfPosition,
"Wallpaper position GConf key is correct");
wpFile.remove(false);
};
restoreSettings = function() {
gconf.setString(DG_IMAGE_KEY, prevImageKey);
gconf.setString(DG_OPTION_KEY, prevOptionKey);
gconf.setBool(DG_DRAW_BG_KEY, prevDrawBgKey);
};
}
} catch (e) {}
checkWallpaper(Ci.nsIShellService.BACKGROUND_TILE, "wallpaper");
checkWallpaper(Ci.nsIShellService.BACKGROUND_STRETCH, "stretched");

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

@ -1,114 +0,0 @@
const GCONF_BG_COLOR_KEY = "/desktop/gnome/background/primary_color";
var gShell;
var gGConf;
/**
* Converts from a rgb numerical color valule (r << 16 | g << 8 | b)
* into a hex string in #RRGGBB format.
*/
function colorToHex(aColor) {
const rMask = 4294901760;
const gMask = 65280;
const bMask = 255;
var r = (aColor & rMask) >> 16;
var g = (aColor & gMask) >> 8;
var b = (aColor & bMask);
return "#" + [r, g, b].map(aInt =>
aInt.toString(16).replace(/^(.)$/, "0$1"))
.join("").toUpperCase();
}
/**
* Converts a color string in #RRGGBB format to a rgb numerical color value
* (r << 16 | g << 8 | b).
*/
function hexToColor(aString) {
return parseInt(aString.substring(1, 3), 16) << 16 |
parseInt(aString.substring(3, 5), 16) << 8 |
parseInt(aString.substring(5, 7), 16);
}
/**
* Checks that setting the GConf background key to aGConfColor will
* result in the Shell component returning a background color equals
* to aExpectedShellColor in #RRGGBB format.
*/
function checkGConfToShellColor(aGConfColor, aExpectedShellColor) {
gGConf.setString(GCONF_BG_COLOR_KEY, aGConfColor);
var shellColor = colorToHex(gShell.desktopBackgroundColor);
Assert.equal(shellColor, aExpectedShellColor);
}
/**
* Checks that setting the background color (in #RRGGBB format) using the Shell
* component will result in having a GConf key for the background color set to
* aExpectedGConfColor.
*/
function checkShellToGConfColor(aShellColor, aExpectedGConfColor) {
gShell.desktopBackgroundColor = hexToColor(aShellColor);
var gconfColor = gGConf.getString(GCONF_BG_COLOR_KEY);
Assert.equal(gconfColor, aExpectedGConfColor);
}
function run_test() {
// This test is Linux specific for now
if (!("@mozilla.org/gnome-gconf-service;1" in Cc))
return;
try {
// If GSettings is available, then the GConf tests
// will fail
Cc["@mozilla.org/gsettings-service;1"].
getService(Ci.nsIGSettingsService).
getCollectionForSchema("org.gnome.desktop.background");
return;
} catch (e) { }
gGConf = Cc["@mozilla.org/gnome-gconf-service;1"].
getService(Ci.nsIGConfService);
gShell = Cc["@mozilla.org/browser/shell-service;1"].
getService(Ci.nsIShellService);
// Save the original background color so that we can restore it
// after the test.
var origGConfColor = gGConf.getString(GCONF_BG_COLOR_KEY);
try {
checkGConfToShellColor("#000", "#000000");
checkGConfToShellColor("#00f", "#0000FF");
checkGConfToShellColor("#b2f", "#BB22FF");
checkGConfToShellColor("#fff", "#FFFFFF");
checkGConfToShellColor("#000000", "#000000");
checkGConfToShellColor("#0000ff", "#0000FF");
checkGConfToShellColor("#b002f0", "#B002F0");
checkGConfToShellColor("#ffffff", "#FFFFFF");
checkGConfToShellColor("#000000000", "#000000");
checkGConfToShellColor("#00f00f00f", "#000000");
checkGConfToShellColor("#aaabbbccc", "#AABBCC");
checkGConfToShellColor("#fffffffff", "#FFFFFF");
checkGConfToShellColor("#000000000000", "#000000");
checkGConfToShellColor("#000f000f000f", "#000000");
checkGConfToShellColor("#00ff00ff00ff", "#000000");
checkGConfToShellColor("#aaaabbbbcccc", "#AABBCC");
checkGConfToShellColor("#111122223333", "#112233");
checkGConfToShellColor("#ffffffffffff", "#FFFFFF");
checkShellToGConfColor("#000000", "#000000000000");
checkShellToGConfColor("#0000FF", "#00000000ffff");
checkShellToGConfColor("#FFFFFF", "#ffffffffffff");
checkShellToGConfColor("#0A0B0C", "#0a0a0b0b0c0c");
checkShellToGConfColor("#A0B0C0", "#a0a0b0b0c0c0");
checkShellToGConfColor("#AABBCC", "#aaaabbbbcccc");
} finally {
gGConf.setString(GCONF_BG_COLOR_KEY, origGConfColor);
}
}

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

@ -1,6 +0,0 @@
[DEFAULT]
head =
firefox-appdir = browser
skip-if = toolkit == 'android'
[test_421977.js]

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

@ -62,7 +62,7 @@ class MozTranslationNotification extends MozElements.Notification {
<menuitem anonid="neverForLanguage" oncommand="this.closest('notification').neverForLanguage();"/>
<menuitem anonid="neverForSite" oncommand="this.closest('notification').neverForSite();" label="&translation.options.neverForSite.label;" accesskey="&translation.options.neverForSite.accesskey;"/>
<menuseparator/>
<menuitem oncommand="openPreferences('paneGeneral', {origin:'translationInfobar'});" label="&translation.options.preferences.label;" accesskey="&translation.options.preferences.accesskey;"/>
<menuitem oncommand="openPreferences('paneGeneral');" label="&translation.options.preferences.label;" accesskey="&translation.options.preferences.accesskey;"/>
<menuitem class="subviewbutton panel-subview-footer" oncommand="this.closest('notification').openProviderAttribution();">
<deck anonid="translationEngine" selectedIndex="0">
<hbox class="translation-attribution">

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

@ -438,7 +438,7 @@ var UITour = {
log.warn("openPreferences: Invalid pane specified");
return false;
}
window.openPreferences(data.pane, { origin: "UITour" });
window.openPreferences(data.pane);
break;
}

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

@ -235,20 +235,27 @@ class UrlbarController {
*
* @param {KeyboardEvent} event
* The DOM KeyboardEvent.
* @param {boolean} executeAction
* Whether the event should actually execute the associated action, or just
* be managed (at a preventDefault() level). This is used when the event
* will be deferred by the event bufferer, but preventDefault() and friends
* should still happen synchronously.
*/
handleKeyNavigation(event) {
handleKeyNavigation(event, executeAction = true) {
const isMac = AppConstants.platform == "macosx";
// Handle readline/emacs-style navigation bindings on Mac.
if (isMac &&
this.view.isOpen &&
event.ctrlKey &&
(event.key == "n" || event.key == "p")) {
this.view.selectBy(1, { reverse: event.key == "p" });
if (executeAction) {
this.view.selectBy(1, { reverse: event.key == "p" });
}
event.preventDefault();
return;
}
if (this.view.isOpen) {
if (this.view.isOpen && executeAction) {
let queryContext = this._lastQueryContext;
if (queryContext) {
this.view.oneOffSearchButtons.handleKeyPress(
@ -264,7 +271,9 @@ class UrlbarController {
switch (event.keyCode) {
case KeyEvent.DOM_VK_ESCAPE:
this.input.handleRevert();
if (executeAction) {
this.input.handleRevert();
}
event.preventDefault();
break;
case KeyEvent.DOM_VK_RETURN:
@ -273,12 +282,16 @@ class UrlbarController {
// Prevent beep on Mac.
event.preventDefault();
}
this.input.handleCommand(event);
if (executeAction) {
this.input.handleCommand(event);
}
break;
case KeyEvent.DOM_VK_TAB:
if (this.view.isOpen) {
this.view.selectBy(1, { reverse: event.shiftKey });
this.userSelectionBehavior = "tab";
if (executeAction) {
this.view.selectBy(1, { reverse: event.shiftKey });
this.userSelectionBehavior = "tab";
}
event.preventDefault();
}
break;
@ -290,18 +303,22 @@ class UrlbarController {
break;
}
if (this.view.isOpen) {
this.userSelectionBehavior = "arrow";
this.view.selectBy(
event.keyCode == KeyEvent.DOM_VK_PAGE_DOWN ||
event.keyCode == KeyEvent.DOM_VK_PAGE_UP ?
if (executeAction) {
this.userSelectionBehavior = "arrow";
this.view.selectBy(
event.keyCode == KeyEvent.DOM_VK_PAGE_DOWN ||
event.keyCode == KeyEvent.DOM_VK_PAGE_UP ?
UrlbarUtils.PAGE_UP_DOWN_DELTA : 1,
{ reverse: event.keyCode == KeyEvent.DOM_VK_UP ||
event.keyCode == KeyEvent.DOM_VK_PAGE_UP });
{ reverse: event.keyCode == KeyEvent.DOM_VK_UP ||
event.keyCode == KeyEvent.DOM_VK_PAGE_UP });
}
} else {
if (this.keyEventMovesCaret(event)) {
break;
}
this.input.startQuery();
if (executeAction) {
this.input.startQuery();
}
}
event.preventDefault();
break;
@ -313,7 +330,8 @@ class UrlbarController {
break;
case KeyEvent.DOM_VK_DELETE:
case KeyEvent.DOM_VK_BACK_SPACE:
if (event.shiftKey && this.view.isOpen && this._handleDeleteEntry()) {
if (event.shiftKey && this.view.isOpen &&
(!executeAction || this._handleDeleteEntry())) {
event.preventDefault();
}
break;

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

@ -1375,6 +1375,16 @@ class UrlbarInput {
}
_on_keydown(event) {
// Due to event deferring, it's possible preventDefault() won't be invoked
// soon enough to actually prevent some of the default behaviors, thus we
// have to handle the event "twice". This first immediate call passes false
// as second argument so that handleKeyNavigation will only simulate the
// event handling, without actually executing actions.
// TODO (Bug 1541806): improve this handling, maybe by delaying actions
// instead of events.
if (this.eventBufferer.shouldDeferEvent(event)) {
this.controller.handleKeyNavigation(event, false);
}
this._toggleActionOverride(event);
this.eventBufferer.maybeDeferEvent(event, () => {
this.controller.handleKeyNavigation(event);

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

@ -31,6 +31,9 @@ skip-if = os != "mac" # Mac only feature
[browser_autoFill_trimURLs.js]
[browser_autoFill_typed.js]
[browser_canonizeURL.js]
support-files =
searchSuggestionEngine.xml
searchSuggestionEngine.sjs
[browser_caret_navigation.js]
[browser_dragdropURL.js]
[browser_dropmarker.js]
@ -41,6 +44,8 @@ skip-if = os != "mac" # Mac only feature
[browser_keyword.js]
support-files =
print_postdata.sjs
searchSuggestionEngine.xml
searchSuggestionEngine.sjs
[browser_locationBarCommand.js]
[browser_locationBarExternalLoad.js]
[browser_moz_action_link.js]

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

@ -55,30 +55,36 @@ add_task(async function checkPrefTurnsOffCanonize() {
await Services.search.setDefault(engine);
registerCleanupFunction(async () => Services.search.setDefault(oldDefaultEngine));
let tabsToClose = [];
// Ensure we don't end up loading something in the current tab becuase it's empty:
if (gBrowser.selectedTab.isEmpty) {
tabsToClose.push(await BrowserTestUtils.openNewForegroundTab({gBrowser, opening: "about:mozilla"}));
}
let initialTabURL = gBrowser.selectedBrowser.currentURI.spec;
let initialTab = gBrowser.selectedTab;
let initialTab = await BrowserTestUtils.openNewForegroundTab({gBrowser, opening: "about:mozilla"});
await SpecialPowers.pushPrefEnv({set: [["browser.urlbar.ctrlCanonizesURLs", false]]});
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser);
let newURL = "http://mochi.test:8888/?terms=example";
// On MacOS CTRL+Enter is not supposed to open in a new tab, because it uses
// CMD+Enter for that.
let promiseLoaded = AppConstants.platform == "macosx" ?
BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, newURL) :
BrowserTestUtils.waitForNewTab(gBrowser);
gURLBar.focus();
gURLBar.selectionStart = gURLBar.selectionEnd =
gURLBar.inputField.value.length;
gURLBar.inputField.value = "exampl";
EventUtils.sendString("e");
EventUtils.synthesizeKey("KEY_Enter", AppConstants.platform == "macosx" ?
{metaKey: true} : {ctrlKey: true});
EventUtils.synthesizeKey("KEY_Enter", {ctrlKey: true});
tabsToClose.push(await promiseTabOpened);
is(initialTab.linkedBrowser.currentURI.spec, initialTabURL,
"Original tab shouldn't have navigated");
for (let t of tabsToClose) {
gBrowser.removeTab(t);
await promiseLoaded;
if (AppConstants.platform == "macosx") {
Assert.equal(initialTab.linkedBrowser.currentURI.spec, newURL,
"Original tab should have navigated");
} else {
Assert.equal(initialTab.linkedBrowser.currentURI.spec, "about:mozilla",
"Original tab shouldn't have navigated");
Assert.equal(gBrowser.selectedBrowser.currentURI.spec, newURL,
"New tab should have navigated");
}
while (gBrowser.tabs.length > 1) {
gBrowser.removeTab(gBrowser.selectedTab, {animate: false});
}
});
@ -93,13 +99,14 @@ add_task(async function autofill() {
// starts with the new search string, so to make sure that doesn't happen and
// that earlier tests don't conflict with this one, start a new search for
// some other string.
gURLBar.focus();
gURLBar.select();
EventUtils.sendString("blah");
// Add a visit that will be autofilled.
await PlacesUtils.history.clear();
await PlacesTestUtils.addVisits([{
uri: "http://example.com/",
transition: PlacesUtils.history.TRANSITIONS.TYPED,
}]);
let testcases = [
@ -117,17 +124,16 @@ add_task(async function autofill() {
for (let [inputValue, expectedURL, options] of testcases) {
let promiseLoad =
BrowserTestUtils.waitForDocLoadAndStopIt(expectedURL, gBrowser.selectedBrowser);
gURLBar.focus();
gURLBar.inputField.value = inputValue.slice(0, -1);
gURLBar.select();
let autofillPromise = promiseAutofill();
EventUtils.sendString(inputValue.slice(-1));
EventUtils.sendString(inputValue);
await autofillPromise;
EventUtils.synthesizeKey("KEY_Enter", options);
await promiseLoad;
// Here again, make sure autofill isn't disabled for the next search. See
// the comment above.
gURLBar.focus();
gURLBar.select();
EventUtils.sendString("blah");
}

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

@ -20,38 +20,50 @@ add_task(async function() {
if (AppConstants.platform == "macosx" ||
AppConstants.platform == "linux") {
if (AppConstants.platform == "linux") {
await checkCaretMoves("KEY_ArrowUp", INITIAL_SELECTION_START, "Selection should be collapsed to its start");
await checkCaretMoves("KEY_ArrowUp", INITIAL_SELECTION_START,
"Selection should be collapsed to its start");
gURLBar.selectionStart = INITIAL_SELECTION_START;
gURLBar.selectionEnd = INITIAL_SELECTION_END;
await checkCaretMoves("KEY_ArrowDown", INITIAL_SELECTION_END, "Selection should be collapsed to its end");
await checkCaretMoves("KEY_ArrowDown", INITIAL_SELECTION_END,
"Selection should be collapsed to its end");
}
await checkCaretMoves("KEY_ArrowDown", gURLBar.textValue.length, "Caret should have moved to the end");
await checkPopupOpens("KEY_ArrowDown", gURLBar.textValue.length);
await checkCaretMoves("KEY_ArrowDown", gURLBar.textValue.length,
"Caret should have moved to the end");
await checkPopupOpens("KEY_ArrowDown");
await checkCaretMoves("KEY_ArrowUp", 0, "Caret should have moved to the start");
await checkPopupOpens("KEY_ArrowUp", 0);
await checkCaretMoves("KEY_ArrowUp", 0,
"Caret should have moved to the start");
await checkPopupOpens("KEY_ArrowUp");
} else {
await checkPopupOpens("KEY_ArrowDown", gURLBar.textValue.length);
await checkPopupOpens("KEY_ArrowUp", gURLBar.textValue.length);
await checkPopupOpens("KEY_ArrowDown");
await checkPopupOpens("KEY_ArrowUp");
}
});
async function checkCaretMoves(key, pos, msg) {
checkIfKeyStartsQuery(key, false);
Assert.equal(UrlbarTestUtils.isPopupOpen(window), false, `${key}: Popup shouldn't be open`);
Assert.equal(gURLBar.selectionStart, gURLBar.selectionEnd, `${key}: Input selection should be empty`);
Assert.equal(UrlbarTestUtils.isPopupOpen(window), false,
`${key}: Popup shouldn't be open`);
Assert.equal(gURLBar.selectionStart, gURLBar.selectionEnd,
`${key}: Input selection should be empty`);
Assert.equal(gURLBar.selectionStart, pos, `${key}: ${msg}`);
}
async function checkPopupOpens(key, expectedCaretPosition) {
async function checkPopupOpens(key) {
// Store current selection and check it doesn't change.
let selectionStart = gURLBar.selectionStart;
let selectionEnd = gURLBar.selectionEnd;
await UrlbarTestUtils.promisePopupOpen(window, () => {
checkIfKeyStartsQuery(key, true);
});
Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0, `${key}: Heuristic result should be selected`);
Assert.equal(gURLBar.selectionStart, gURLBar.selectionEnd, `${key}: Input selection should be empty`);
Assert.equal(gURLBar.selectionStart, expectedCaretPosition, `${key}: Caret is at the expected position`);
Assert.equal(UrlbarTestUtils.getSelectedIndex(window), 0,
`${key}: Heuristic result should be selected`);
Assert.equal(gURLBar.selectionStart, selectionStart,
`${key}: Input selection start should not change`);
Assert.equal(gURLBar.selectionEnd, selectionEnd,
`${key}: Input selection end should not change`);
await UrlbarTestUtils.promisePopupClose(window);
}

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

@ -267,7 +267,7 @@ FormAutofillParent.prototype = {
}
case "FormAutofill:OpenPreferences": {
const win = BrowserWindowTracker.getTopWindow();
win.openPreferences("privacy-form-autofill", {origin: "autofillFooter"});
win.openPreferences("privacy-form-autofill");
break;
}
case "FormAutofill:GetDecryptedString": {
@ -453,8 +453,7 @@ FormAutofillParent.prototype = {
return;
}
target.ownerGlobal.openPreferences("privacy-address-autofill",
{origin: "autofillDoorhanger"});
target.ownerGlobal.openPreferences("privacy-address-autofill");
};
} else {
// We want to exclude the first time form filling.

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

@ -150,7 +150,7 @@
return;
}
window.openPreferences("privacy-form-autofill", {origin: "autofillFooter"});
window.openPreferences("privacy-form-autofill");
});
}

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

@ -0,0 +1,45 @@
# 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/.
customize-mode-restore-defaults =
.label = Restore Defaults
customize-mode-menu-and-toolbars-header = Drag your favorite items into the toolbar or overflow menu.
customize-mode-overflow-list-title = Overflow Menu
customize-mode-uidensity =
.label = Density
customize-mode-done =
.label = Done
customize-mode-lwthemes-menu-manage =
.label = Manage
.accesskey = M
customize-mode-toolbars =
.label = Toolbars
customize-mode-titlebar =
.label = Title Bar
customize-mode-uidensity-menu-touch =
.label = Touch
.accesskey = T
.tooltiptext = Touch
customize-mode-uidensity-auto-touch-mode-checkbox =
.label = Use Touch for Tablet Mode
customize-mode-extra-drag-space =
.label = Drag Space
customize-mode-lwthemes =
.label = Themes
customize-mode-overflow-list-description = Drag and drop items here to keep them within reach but out of your toolbar…
customize-mode-uidensity-menu-normal =
.label = Normal
.accesskey = N
.tooltiptext = Normal
customize-mode-uidensity-menu-compact =
.label = Compact
.accesskey = C
.tooltiptext = Compact
customize-mode-lwthemes-menu-get-more =
.label = Get More Themes
.accesskey = G
customize-mode-undo-cmd =
.label = Undo
customize-mode-lwthemes-my-themes =
.value = My Themes

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

@ -125,6 +125,8 @@ policy-SearchBar = Set the default location of the search bar. The user is still
policy-SearchEngines = Configure search engine settings. This policy is only available on the Extended Support Release (ESR) version.
policy-SearchSuggestEnabled = Enable or disable search suggestions.
# For more information, see https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/PKCS11/Module_Installation
policy-SecurityDevices = Install PKCS #11 modules.

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

@ -867,41 +867,6 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY syncReAuthItem.accesskey "R">
<!ENTITY syncToolbarButton.label "Sync">
<!ENTITY customizeMode.menuAndToolbars.header3 "Drag your favorite items into the toolbar or overflow menu.">
<!ENTITY customizeMode.restoreDefaults "Restore Defaults">
<!ENTITY customizeMode.done "Done">
<!ENTITY customizeMode.titlebar "Title Bar">
<!ENTITY customizeMode.extraDragSpace "Drag Space">
<!ENTITY customizeMode.toolbars2 "Toolbars">
<!ENTITY customizeMode.lwthemes "Themes">
<!ENTITY customizeMode.lwthemes.myThemes "My Themes">
<!ENTITY customizeMode.lwthemes.menuManage "Manage">
<!ENTITY customizeMode.lwthemes.menuManage.accessKey "M">
<!ENTITY customizeMode.lwthemes.menuGetMore "Get More Themes">
<!ENTITY customizeMode.lwthemes.menuGetMore.accessKey "G">
<!ENTITY customizeMode.overflowList.title2 "Overflow Menu">
<!ENTITY customizeMode.overflowList.description "Drag and drop items here to keep them within reach but out of your toolbar…">
<!ENTITY customizeMode.uidensity "Density">
<!-- LOCALIZATION NOTE (customizeMode.uidensity.menuNormal.*):
Normal is displayed in the Customize screen, under the Density menu. -->
<!ENTITY customizeMode.uidensity.menuNormal.label "Normal">
<!ENTITY customizeMode.uidensity.menuNormal.tooltip "Normal">
<!ENTITY customizeMode.uidensity.menuNormal.accessKey "N">
<!-- LOCALIZATION NOTE (customizeMode.uidensity.menuCompact.*):
Compact is displayed in the Customize screen, under the Density menu.
Its an adjective (Density -> Compact). -->
<!ENTITY customizeMode.uidensity.menuCompact.label "Compact">
<!ENTITY customizeMode.uidensity.menuCompact.tooltip "Compact">
<!ENTITY customizeMode.uidensity.menuCompact.accessKey "C">
<!-- LOCALIZATION NOTE (customizeMode.uidensity.menuTouch.*):
Touch is displayed in the Customize screen, under the Density menu.
Its an adjective (Density -> Touch), and it means that control layout is
optimized for touch devices. -->
<!ENTITY customizeMode.uidensity.menuTouch.label "Touch">
<!ENTITY customizeMode.uidensity.menuTouch.tooltip "Touch">
<!ENTITY customizeMode.uidensity.menuTouch.accessKey "T">
<!ENTITY customizeMode.uidensity.autoTouchMode.checkbox.label "Use Touch for Tablet Mode">
<!ENTITY customizeMode.autoHideDownloadsButton.label "Auto-hide">
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">

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

@ -420,7 +420,7 @@ var ContentSearch = {
},
_onMessageManageEngines(msg) {
msg.target.ownerGlobal.openPreferences("paneSearch", { origin: "contentSearch" });
msg.target.ownerGlobal.openPreferences("paneSearch");
},
async _onMessageGetSuggestions(msg, data) {

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

@ -12,8 +12,6 @@ var EXPORTED_SYMBOLS = ["HomePage"];
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
const kPrefName = "browser.startup.homepage";
@ -53,23 +51,12 @@ let HomePage = {
(aWindow && PrivateBrowsingUtils.isWindowPrivate(aWindow))) {
// If an extension controls the setting and does not have private
// browsing permission, use the default setting.
let extensionInfo;
try {
extensionInfo = ExtensionSettingsStore.getSetting("prefs", "homepage_override");
} catch (e) {
// ExtensionSettings may not be initialized if no extensions are enabled. If
// we have some indication that an extension controls the homepage, return
// the defaults instead.
if (homePages.includes("moz-extension://")) {
return this.getDefault();
}
}
if (extensionInfo) {
let policy = WebExtensionPolicy.getByID(extensionInfo.id);
if (!policy || !policy.privateBrowsingAllowed) {
return this.getDefault();
}
let extensionControlled = Services.prefs.getBoolPref("browser.startup.homepage_override.extensionControlled", false);
let privateAllowed = Services.prefs.getBoolPref("browser.startup.homepage_override.privateAllowed", false);
// There is a potential on upgrade that the prefs are not set yet, so we double check
// for moz-extension.
if (!privateAllowed && (extensionControlled || homePages.includes("moz-extension://"))) {
return this.getDefault();
}
}

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

@ -388,15 +388,16 @@ notification[value="translation"] menulist > .menulist-dropmarker {
}
.browserContainer > findbar {
background-color: var(--toolbar-bgcolor);
color: var(--toolbar-color);
background-color: var(--toolbar-non-lwt-bgcolor);
color: var(--toolbar-non-lwt-textcolor);
text-shadow: none;
}
.browserContainer > findbar:-moz-lwtheme {
:root:not([lwtheme-image]) .browserContainer > findbar:-moz-lwtheme {
background-color: var(--lwt-accent-color);
background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor));
border-top-color: var(--chrome-content-separator-color);
text-shadow: none;
color: var(--toolbar-color);
}
/* Tabstrip */

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

@ -564,7 +564,7 @@ html|input.urlbar-input {
text-shadow: none;
}
.browserContainer > findbar:-moz-lwtheme {
:root:not([lwtheme-image]) .browserContainer > findbar:-moz-lwtheme {
background-color: var(--lwt-accent-color);
background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor));
border-top-color: var(--chrome-content-separator-color);

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

@ -18,11 +18,6 @@
width: 16px;
}
.content-blocking-category .checkbox-label-box {
-moz-context-properties: fill;
fill: currentColor;
}
#contentBlockingTrackingProtectionCheckbox > .checkbox-label-box {
list-style-image: url("chrome://browser/skin/controlcenter/trackers.svg");
}
@ -56,7 +51,10 @@
}
.content-blocking-icon,
.permission-icon {
.permission-icon,
.content-blocking-category .checkbox-label-box,
.extra-information-label > image,
.arrowhead {
-moz-context-properties: fill;
fill: currentColor;
}
@ -139,10 +137,9 @@
min-width: 20px;
max-height: 20px;
max-width: 20px;
list-style-image: url("chrome://global/skin/icons/arrow-dropdown-12.svg");
background-color: transparent;
background-image: url("chrome://global/skin/icons/arrow-dropdown-12.svg");
background-repeat: no-repeat;
background-position: center;
padding: 3px;
}
.arrowhead:not([disabled]):hover {
@ -155,7 +152,7 @@
}
.arrowhead.up {
background-image: url("chrome://global/skin/icons/arrow-up-12.svg");
list-style-image: url("chrome://global/skin/icons/arrow-up-12.svg");
}
.arrowhead > .button-box {

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

@ -31,7 +31,7 @@
margin: 9px;
}
.icon-buttons > radio > [data-identity-icon] {
.icon-buttons > radio > .userContext-icon {
fill: #4d4d4d;
}
@ -39,7 +39,7 @@
padding-inline-start: 2px;
}
radio > [data-identity-icon] {
radio > .userContext-icon {
inline-size: 22px;
block-size: 22px;
}

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

@ -683,15 +683,16 @@ html|*.urlbar-input:-moz-lwtheme::placeholder,
}
.browserContainer > findbar {
background-color: var(--toolbar-bgcolor);
color: var(--toolbar-color);
background-color: var(--toolbar-non-lwt-bgcolor);
color: var(--toolbar-non-lwt-textcolor);
text-shadow: none;
}
.browserContainer > findbar:-moz-lwtheme {
:root:not([lwtheme-image]) .browserContainer > findbar:-moz-lwtheme {
background-color: var(--lwt-accent-color);
background-image: linear-gradient(var(--toolbar-bgcolor), var(--toolbar-bgcolor));
border-top-color: var(--chrome-content-separator-color);
text-shadow: none;
color: var(--toolbar-color);
}
/* Tabstrip */

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

@ -73,7 +73,7 @@ let prefHelper = async function(primary, customFn = null) {
readyPromise = TestUtils.topicObserved("sync-pane-loaded");
}
browserWindow.openPreferences(primary, {origin: "mozscreenshots"});
browserWindow.openPreferences(primary);
await readyPromise;

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

@ -57,14 +57,14 @@ function inspectDebugTarget(type, id) {
// updated so this is not an issue. On remote runtimes however, trying to inspect a
// worker a second time after closing the corresponding about:devtools-toolbox tab
// will fail. See Bug 1534201.
window.open(`about:devtools-toolbox?type=${type.toLowerCase()}&id=${id}`);
window.open(`about:devtools-toolbox?type=${type}&id=${id}`);
} else {
window.open(`about:devtools-toolbox?type=${type.toLowerCase()}&id=${id}` +
window.open(`about:devtools-toolbox?type=${type}&id=${id}` +
`&remoteId=${remoteId}`);
}
dispatch(Actions.recordTelemetryEvent("inspect", {
"target_type": type,
"target_type": type.toUpperCase(),
"runtime_type": runtime.type,
}));
};

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

@ -4,8 +4,8 @@
"use strict";
const { CONNECTION_TYPES } =
require("devtools/client/shared/remote-debugging/remote-client-manager");
const { CONNECTION_TYPES, DEBUG_TARGET_TYPES } =
require("devtools/client/shared/remote-debugging/constants");
const actionTypes = {
ADB_ADDON_INSTALL_START: "ADB_ADDON_INSTALL_START",
@ -67,12 +67,7 @@ const actionTypes = {
WATCH_RUNTIME_SUCCESS: "WATCH_RUNTIME_SUCCESS",
};
const DEBUG_TARGETS = {
EXTENSION: "EXTENSION",
PROCESS: "PROCESS",
TAB: "TAB",
WORKER: "WORKER",
};
const DEBUG_TARGETS = DEBUG_TARGET_TYPES;
const DEBUG_TARGET_PANE = {
INSTALLED_EXTENSION: "installedExtension",

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

@ -5,6 +5,7 @@
"use strict";
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { DEBUG_TARGETS } = require("../constants");
const extensionTargetDetails = {
// actor ID for this extention.
@ -59,8 +60,8 @@ const debugTarget = {
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
// display name for the debug target.
name: PropTypes.string.isRequired,
// one of "EXTENSION", "TAB", "WORKER".
type: PropTypes.string.isRequired,
// one of "extension", "tab", "worker", "process".
type: PropTypes.oneOf(Object.values(DEBUG_TARGETS)).isRequired,
};
exports.debugTarget = PropTypes.shape(debugTarget);

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

@ -35,8 +35,6 @@ export function paused(pauseInfo: Pause) {
const { thread, frames, why, loadedObjects } = pauseInfo;
const topFrame = frames.length > 0 ? frames[0] : null;
client.onPauseChange(thread, true);
dispatch({
type: "PAUSED",
thread,

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

@ -24,8 +24,6 @@ export function resumed(packet: ResumedPacket) {
const wasPausedInEval = inDebuggerEval(why);
const wasStepping = isStepping(getState(), thread);
client.onPauseChange(thread, false);
dispatch({ type: "RESUME", thread, wasStepping });
const cx = getThreadContext(getState());

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

@ -70,8 +70,7 @@ const mockThreadClient = {
}
});
},
getBreakpointPositions: async () => ({}),
onPauseChange() {}
getBreakpointPositions: async () => ({})
};
const mockFrameId = "1";

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

@ -35,8 +35,7 @@ const threadClient = {
evaluate: async expression => ({ result: evaluationResult[expression] }),
evaluateExpressions: async expressions =>
expressions.map(expression => ({ result: evaluationResult[expression] })),
getBreakpointPositions: async () => ({}),
onPauseChange() {}
getBreakpointPositions: async () => ({})
};
const sourceMaps = {

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

@ -46,8 +46,7 @@ const mockThreadClient = {
matchProp: "to"
});
});
},
onPauseChange() {}
}
};
describe("expressions", () => {

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

@ -78,6 +78,5 @@ export const sourceThreadClient = {
threadClient: async () => {},
getFrameScopes: async () => {},
evaluateExpressions: async () => {},
getBreakpointPositions: async () => ({}),
onPauseChange() {}
getBreakpointPositions: async () => ({})
};

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

@ -303,10 +303,6 @@ function reload(): Promise<*> {
return tabTarget.reload();
}
function onPauseChange(thread: string, paused: boolean) {
tabTarget.emit("pause-change", { thread, paused });
}
function getProperties(thread: string, grip: Grip): Promise<*> {
const objClient = lookupThreadClient(thread).pauseGrip(grip);
@ -508,7 +504,6 @@ const clientCommands = {
evaluateExpressions,
navigate,
reload,
onPauseChange,
getProperties,
getFrameScopes,
pauseOnExceptions,

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

@ -51,6 +51,7 @@
"waitForThreadEvents": false,
"waitForState": false,
"waitForElement": false,
"waitForAllElements": false,
"waitForElementWithSelector": false,
"waitForPaused": false,
"waitForSources": false,
@ -59,7 +60,10 @@
"waitForSelectedSource": false,
"waitForBreakpoint": false,
"waitForBreakpointCount": false,
"waitForCondition": false,
"waitForLog": false,
"isPaused": false,
"assertClass": false,
"assertSourceCount": false,
"assertEditorBreakpoint": false,
"assertBreakpointSnippet": false,
@ -92,7 +96,9 @@
"clickDOMElement": false,
"altClickElement": false,
"rightClickElement": false,
"rightClickEl": false,
"clickGutter": false,
"typeInPanel": false,
"selectMenuItem": false,
"selectContextMenuItem": false,
"togglePauseOnExceptions": false,

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

@ -1,111 +1,104 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.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 getColumnBreakpointElements(dbg) {
return findAllElementsWithSelector(dbg, ".column-breakpoint");
async function enableFirstBreakpoint(dbg) {
getCM(dbg).setCursor({ line: 32, ch: 0 });
await addBreakpoint(dbg, "long", 32);
const bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
ok(bpMarkers.length === 2, "2 column breakpoints");
assertClass(bpMarkers[0], "active");
assertClass(bpMarkers[1], "active", false);
}
async function assertConditionalBreakpointIsFocused(dbg) {
const input = findElement(dbg, "conditionalPanelInput");
await waitForElementFocus(dbg, input);
}
async function enableSecondBreakpoint(dbg) {
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
function waitForElementFocus(dbg, el) {
const doc = dbg.win.document;
return waitFor(() => doc.activeElement == el && doc.hasFocus());
}
bpMarkers[1].click();
await waitForBreakpointCount(dbg, 2);
function hasCondition(marker) {
return marker.classList.contains("has-condition");
bpMarkers = findAllElements(dbg, "columnBreakpoints");
assertClass(bpMarkers[1], "active");
await waitForAllElements(dbg, "breakpointItems", 2);
}
async function setConditionalBreakpoint(dbg, index, condition) {
const {
addConditionalBreakpoint,
editConditionalBreakpoint
} = selectors.gutterContextMenu;
// Make this work with either add or edit menu items
const selector = `${addConditionalBreakpoint},${editConditionalBreakpoint}`;
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
rightClickEl(dbg, bpMarkers[index]);
selectContextMenuItem(dbg, selectors.addConditionItem);
await typeInPanel(dbg, condition);
await waitForCondition(dbg, condition);
rightClickElement(dbg, "breakpointItem", index);
selectContextMenuItem(dbg, selector);
await waitForElement(dbg, "conditionalPanelInput");
await assertConditionalBreakpointIsFocused(dbg);
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, condition);
pressKey(dbg, "Enter");
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
assertClass(bpMarkers[index], "has-condition");
}
function removeBreakpointViaContext(dbg, index) {
rightClickElement(dbg, "breakpointItem", index);
selectContextMenuItem(dbg, "#node-menu-delete-self");
async function setLogPoint(dbg, index, expression) {
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
rightClickEl(dbg, bpMarkers[index]);
selectContextMenuItem(dbg, selectors.addLogItem);
await typeInPanel(dbg, expression);
await waitForLog(dbg, expression);
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
assertClass(bpMarkers[index], "has-log");
}
async function disableBreakpoint(dbg, index) {
rightClickElement(dbg, "columnBreakpoints");
selectContextMenuItem(dbg, selectors.disableItem);
await waitForState(dbg, state => {
const bp = dbg.selectors.getBreakpointsList(state)[index];
return bp.disabled;
});
const bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
assertClass(bpMarkers[0], "disabled");
}
async function removeFirstBreakpoint(dbg) {
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
bpMarkers[0].click();
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
assertClass(bpMarkers[0], "active", false);
}
async function removeAllBreakpoints(dbg, line, count) {
clickGutter(dbg, 32);
await waitForBreakpointCount(dbg, 0);
ok(findAllElements(dbg, "columnBreakpoints").length == 0);
}
// Test enabling and disabling a breakpoint using the check boxes
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html", "simple1");
await pushPref("devtools.debugger.features.column-breakpoints", false);
await selectSource(dbg, "long");
if(!Services.prefs.getBoolPref("devtools.debugger.features.column-breakpoints")) {
ok(true, "This test only applies when column breakpoints are on");
return;
}
info("1. Add a column breakpoint on line 32");
await enableFirstBreakpoint(dbg);
await selectSource(dbg, "simple1");
info("2. Click on the second breakpoint on line 32");
await enableSecondBreakpoint(dbg);
// Scroll down to desired line so that column breakpoints render
getCM(dbg).setCursor({ line: 15, ch: 0 });
info("3. Add a condition to the first breakpoint");
await setConditionalBreakpoint(dbg, 0, "foo");
// Create a breakpoint at 15:undefined
await addBreakpoint(dbg, "simple1", 15);
info("4. Add a log to the first breakpoint");
await setLogPoint(dbg, 0, "bar");
// Wait for column breakpoint markers
await waitForElementWithSelector(dbg, ".column-breakpoint");
info("5. Disable the first breakpoint");
await disableBreakpoint(dbg, 0);
let columnBreakpointMarkers = getColumnBreakpointElements(dbg);
ok(
columnBreakpointMarkers.length === 2,
"2 column breakpoint markers display"
);
info("6. Remove the first breakpoint");
await removeFirstBreakpoint(dbg);
// Create a breakpoint at 15:8
columnBreakpointMarkers[0].click();
info("7. Add a condition to the second breakpoint");
await setConditionalBreakpoint(dbg, 1, "foo2");
// Create a breakpoint at 15:28
columnBreakpointMarkers[1].click();
// Wait for breakpoints in right panel to render
await waitForState(dbg, state => {
return dbg.win.document.querySelectorAll(".breakpoints-list .breakpoint").length === 3;
})
// Scroll down in secondary pane so element we want to right-click is showing
dbg.win.document.querySelector(".secondary-panes").scrollTop = 100;
// Set a condition at 15:8
await setConditionalBreakpoint(dbg, 4, "Eight");
// Ensure column breakpoint is yellow
await waitForElementWithSelector(dbg, ".column-breakpoint.has-condition");
// Remove the breakpoint from 15:undefined via the secondary pane context menu
removeBreakpointViaContext(dbg, 3);
// Ensure that there's still a marker on line 15
await waitForState(dbg, state => dbg.selectors.getBreakpointCount(state) == 2);
await waitForElementWithSelector(dbg, ".column-breakpoint.has-condition");
columnBreakpointMarkers = getColumnBreakpointElements(dbg);
ok(hasCondition(columnBreakpointMarkers[0]), "First column breakpoint has conditional style");
// Remove the breakpoint from 15:8
removeBreakpointViaContext(dbg, 3);
// Ensure there's still a marker and it has no condition
await waitForState(dbg, state => dbg.selectors.getBreakpointCount(state) == 1);
await waitForElementWithSelector(dbg, ".column-breakpoint");
// Ensure the first column breakpoint has no conditional style
await waitFor(() => !hasCondition(getColumnBreakpointElements(dbg)[0]));
info("8. test removing the breakpoints by clicking in the gutter");
await removeAllBreakpoints(dbg, 32, 0);
});

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

@ -31,27 +31,6 @@ function assertEditorBreakpoint(
);
}
function waitForElementFocus(dbg, el) {
const doc = dbg.win.document;
return waitFor(() => doc.activeElement == el && doc.hasFocus());
}
function waitForBreakpointWithCondition(dbg, url, line, cond) {
return waitForState(dbg, () => {
const bp = findBreakpoint(dbg, url, line);
return (
bp && bp.options.condition && (!cond || bp.options.condition == cond)
);
});
}
function waitForBreakpointWithLog(dbg, url, line) {
return waitForState(dbg, () => {
const bp = findBreakpoint(dbg, url, line);
return bp && bp.options.logValue;
});
}
function waitForBreakpointWithoutCondition(dbg, url, line) {
return waitForState(dbg, () => {
const bp = findBreakpoint(dbg, url, line);
@ -60,37 +39,21 @@ function waitForBreakpointWithoutCondition(dbg, url, line) {
}
async function setConditionalBreakpoint(dbg, index, condition) {
const {
addConditionalBreakpoint,
editConditionalBreakpoint
} = selectors.gutterContextMenu;
// Make this work with either add or edit menu items
const selector = `${addConditionalBreakpoint},${editConditionalBreakpoint}`;
const { addConditionItem, editConditionItem } = selectors;
const selector = `${addConditionItem},${editConditionItem}`;
rightClickElement(dbg, "gutter", index);
selectContextMenuItem(dbg, selector);
await waitForElement(dbg, "conditionalPanelInput");
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, condition);
pressKey(dbg, "Enter");
typeInPanel(dbg, condition);
}
async function setLogPoint(dbg, index, value) {
const { addLogPoint, editLogPoint } = selectors.gutterContextMenu;
// Make this work with either add or edit menu items
const selector = `${addLogPoint},${editLogPoint}`;
rightClickElement(dbg, "gutter", index);
selectContextMenuItem(dbg, selector);
await waitForElement(dbg, "conditionalPanelInput");
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, value);
pressKey(dbg, "Enter");
selectContextMenuItem(
dbg,
`${selectors.addLogItem},${selectors.editLogItem}`
);
await typeInPanel(dbg, value);
}
add_task(async function() {
@ -101,9 +64,9 @@ add_task(async function() {
await selectSource(dbg, "simple2");
await waitForSelectedSource(dbg, "simple2");
info("Set condition `1`");
await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "SET_BREAKPOINT");
await waitForBreakpointWithCondition(dbg, "simple2", 5);
await waitForCondition(dbg, 1);
let bp = findBreakpoint(dbg, "simple2", 5);
is(bp.options.condition, "1", "breakpoint is created with the condition");
@ -111,7 +74,7 @@ add_task(async function() {
info("Edit the conditional breakpoint set above");
await setConditionalBreakpoint(dbg, 5, "2");
await waitForBreakpointWithCondition(dbg, "simple2", 5, "12");
await waitForCondition(dbg, 12);
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.options.condition, "12", "breakpoint is created with the condition");
@ -127,7 +90,7 @@ add_task(async function() {
clickElement(dbg, "gutter", 5);
await waitForDispatch(dbg, "SET_BREAKPOINT");
await setConditionalBreakpoint(dbg, 5, "1");
await waitForBreakpointWithCondition(dbg, "simple2", 5);
await waitForCondition(dbg, 1);
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.options.condition, "1", "breakpoint is created with the condition");
@ -142,7 +105,7 @@ add_task(async function() {
info('Add "log point"');
await setLogPoint(dbg, 5, "44");
await waitForBreakpointWithLog(dbg, "simple2", 5);
await waitForLog(dbg, 44);
await assertEditorBreakpoint(dbg, 5, { hasLog: true });
bp = findBreakpoint(dbg, "simple2", 5);

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

@ -204,11 +204,24 @@ async function waitForElement(dbg, name, ...args) {
return findElement(dbg, name, ...args);
}
async function waitForAllElements(dbg, name, count = 1) {
await waitUntil(() => findAllElements(dbg, name).length >= count);
return findAllElements(dbg, name);
}
async function waitForElementWithSelector(dbg, selector) {
await waitUntil(() => findElementWithSelector(dbg, selector));
return findElementWithSelector(dbg, selector);
}
function assertClass(el, className, exists = true) {
if (exists) {
ok(el.classList.contains(className), `${className} class exists`);
} else {
ok(!el.classList.contains(className), `${className} class does not exist`);
}
}
function waitForSelectedLocation(dbg, line) {
return waitForState(dbg, state => {
const location = dbg.selectors.getSelectedLocation(state);
@ -487,6 +500,22 @@ async function waitForPaused(dbg, url) {
await waitForSelectedSource(dbg, url);
}
function waitForCondition(dbg, condition) {
return waitForState(dbg, state =>
dbg.selectors
.getBreakpointsList(state)
.find(bp => bp.options.condition == condition)
);
}
function waitForLog(dbg, logValue) {
return waitForState(dbg, state =>
dbg.selectors
.getBreakpointsList(state)
.find(bp => bp.options.logValue == logValue)
);
}
/*
* useful for when you want to see what is happening
* e.g await waitForever()
@ -1190,6 +1219,7 @@ const selectors = {
removeOthers: "#node-menu-delete-other",
removeCondition: "#node-menu-remove-condition"
},
columnBreakpoints: ".column-breakpoint",
scopes: ".scopes-list",
scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`,
scopeValue: i =>
@ -1197,15 +1227,13 @@ const selectors = {
frame: i => `.frames [role="list"] [role="listitem"]:nth-child(${i})`,
frames: '.frames [role="list"] [role="listitem"]',
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
// These work for bobth the breakpoint listing and gutter marker
gutterContextMenu: {
addConditionalBreakpoint:
"#node-menu-add-condition, #node-menu-add-conditional-breakpoint",
editConditionalBreakpoint:
"#node-menu-edit-condition, #node-menu-edit-conditional-breakpoint",
addLogPoint: "#node-menu-add-log-point",
editLogPoint: "#node-menu-edit-log-point"
},
addConditionItem:
"#node-menu-add-condition, #node-menu-add-conditional-breakpoint",
editConditionItem:
"#node-menu-edit-condition, #node-menu-edit-conditional-breakpoint",
addLogItem: "#node-menu-add-log-point",
editLogItem: "#node-menu-edit-log-point",
disableItem: "#node-menu-disable-breakpoint",
menuitem: i => `menupopup menuitem:nth-child(${i})`,
pauseOnExceptions: ".pause-exceptions",
breakpoint: ".CodeMirror-code > .new-breakpoint",
@ -1339,12 +1367,12 @@ function altClickElement(dbg, elementName, ...args) {
function rightClickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
const doc = dbg.win.document;
return rightClickEl(dbg, doc.querySelector(selector));
}
return EventUtils.synthesizeMouseAtCenter(
doc.querySelector(selector),
{ type: "contextmenu" },
dbg.win
);
function rightClickEl(dbg, el) {
const doc = dbg.win.document;
EventUtils.synthesizeMouseAtCenter(el, { type: "contextmenu" }, dbg.win);
}
async function clickGutter(dbg, line) {
@ -1363,6 +1391,15 @@ function selectContextMenuItem(dbg, selector) {
return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win);
}
async function typeInPanel(dbg, text) {
await waitForElement(dbg, "conditionalPanelInput");
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, text);
pressKey(dbg, "Enter");
}
/**
* Toggles the debugger call stack accordian.
*

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

@ -6,8 +6,8 @@
const { PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { CONNECTION_TYPES } =
require("devtools/client/shared/remote-debugging/remote-client-manager");
const { CONNECTION_TYPES, DEBUG_TARGET_TYPES } =
require("devtools/client/shared/remote-debugging/constants");
/**
* This is header that should be displayed on top of the toolbox when using
@ -16,12 +16,15 @@ const { CONNECTION_TYPES } =
class DebugTargetInfo extends PureComponent {
static get propTypes() {
return {
deviceDescription: PropTypes.shape({
brandName: PropTypes.string.isRequired,
channel: PropTypes.string.isRequired,
connectionType: PropTypes.string.isRequired,
deviceName: PropTypes.string,
version: PropTypes.string.isRequired,
debugTargetData: PropTypes.shape({
connectionType: PropTypes.oneOf(Object.values(CONNECTION_TYPES)).isRequired,
deviceDescription: PropTypes.shape({
brandName: PropTypes.string.isRequired,
channel: PropTypes.string.isRequired,
deviceName: PropTypes.string,
version: PropTypes.string.isRequired,
}).isRequired,
targetType: PropTypes.oneOf(Object.values(DEBUG_TARGET_TYPES)).isRequired,
}).isRequired,
L10N: PropTypes.object.isRequired,
toolbox: PropTypes.object.isRequired,
@ -29,8 +32,9 @@ class DebugTargetInfo extends PureComponent {
}
getRuntimeText() {
const { deviceDescription, L10N } = this.props;
const { brandName, version, connectionType } = deviceDescription;
const { debugTargetData, L10N } = this.props;
const { brandName, version } = debugTargetData.deviceDescription;
const { connectionType } = debugTargetData;
return (connectionType === CONNECTION_TYPES.THIS_FIREFOX)
? L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel.thisFirefox", version)
@ -38,7 +42,7 @@ class DebugTargetInfo extends PureComponent {
}
getAssetsForConnectionType() {
const { connectionType } = this.props.deviceDescription;
const { connectionType } = this.props.debugTargetData;
switch (connectionType) {
case CONNECTION_TYPES.USB:
@ -54,8 +58,40 @@ class DebugTargetInfo extends PureComponent {
}
}
getAssetsForDebugTargetType() {
const { targetType } = this.props.debugTargetData;
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=1520723
// Show actual favicon (currently toolbox.target.activeTab.favicon
// is unpopulated)
const favicon = "chrome://devtools/skin/images/globe.svg";
switch (targetType) {
case DEBUG_TARGET_TYPES.EXTENSION:
return {
image: "chrome://devtools/skin/images/debugging-addons.svg",
l10nId: "toolbox.debugTargetInfo.targetType.extension",
};
case DEBUG_TARGET_TYPES.PROCESS:
return {
image: "chrome://devtools/skin/images/settings.svg",
l10nId: "toolbox.debugTargetInfo.targetType.process",
};
case DEBUG_TARGET_TYPES.TAB:
return {
image: favicon,
l10nId: "toolbox.debugTargetInfo.targetType.tab",
};
case DEBUG_TARGET_TYPES.WORKER:
return {
image: "chrome://devtools/skin/images/debugging-workers.svg",
l10nId: "toolbox.debugTargetInfo.targetType.worker",
};
}
}
shallRenderConnection() {
const { connectionType } = this.props.deviceDescription;
const { connectionType } = this.props.debugTargetData;
const renderableTypes = [
CONNECTION_TYPES.USB,
CONNECTION_TYPES.NETWORK,
@ -65,7 +101,7 @@ class DebugTargetInfo extends PureComponent {
}
renderConnection() {
const { connectionType } = this.props.deviceDescription;
const { connectionType } = this.props.debugTargetData;
const { image, l10nId } = this.getAssetsForConnectionType();
return dom.span(
@ -78,7 +114,7 @@ class DebugTargetInfo extends PureComponent {
}
renderRuntime() {
const { channel, deviceName } = this.props.deviceDescription;
const { channel, deviceName } = this.props.debugTargetData.deviceDescription;
const channelIcon =
(channel === "release" || channel === "beta" || channel === "aurora") ?
@ -98,16 +134,14 @@ class DebugTargetInfo extends PureComponent {
renderTarget() {
const title = this.props.toolbox.target.name;
const url = this.props.toolbox.target.url;
// TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=1520723
// Show actual favicon (currently toolbox.target.activeTab.favicon
// is unpopulated)
const favicon = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
const { image, l10nId } = this.getAssetsForDebugTargetType();
return dom.span(
{
className: "iconized-label",
},
dom.img({ src: favicon, alt: "favicon"}),
dom.img({ src: image, alt: this.props.L10N.getStr(l10nId)}),
title ? dom.b({ className: "devtools-ellipsis-text js-target-title"}, title) : null,
dom.span({ className: "devtools-ellipsis-text" }, url),
);

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

@ -96,10 +96,11 @@ class ToolboxToolbar extends Component {
// Because in the component we cannot compare the visibility since the
// button definition instance in toolboxButtons will be unchanged.
visibleToolboxButtonCount: PropTypes.number,
// Flag whether need to show DebugTargetInfo.
showDebugTargetInfo: PropTypes.bool,
// Device description for DebugTargetInfo component.
deviceDescription: PropTypes.object,
// Data to show debug target info, if needed
debugTargetData: PropTypes.shape({
deviceDescription: PropTypes.object.isRequired,
targetType: PropTypes.string.isRequired,
}),
};
}
@ -422,7 +423,7 @@ class ToolboxToolbar extends Component {
* render functions for how each of the sections is rendered.
*/
render() {
const {deviceDescription, L10N, showDebugTargetInfo, toolbox} = this.props;
const { L10N, debugTargetData, toolbox} = this.props;
const classnames = ["devtools-tabbar"];
const startButtons = this.renderToolboxButtonsStart();
const endButtons = this.renderToolboxButtonsEnd();
@ -448,8 +449,9 @@ class ToolboxToolbar extends Component {
)
: div({ className: classnames.join(" ") });
const debugTargetInfo =
showDebugTargetInfo ? DebugTargetInfo({ deviceDescription, L10N, toolbox }) : null;
const debugTargetInfo = debugTargetData
? DebugTargetInfo({ debugTargetData, L10N, toolbox })
: null;
if (toolbox.target.canRewind) {
return div(

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

@ -84,7 +84,7 @@ async function testWindowHost() {
const win = Services.wm.getMostRecentWindow("devtools:toolbox");
ok(win, "toolbox separate window exists");
const iframe = win.document.getElementById("toolbox-iframe");
const iframe = win.document.querySelector(".devtools-toolbox-window-iframe");
checkToolboxLoaded(iframe);
}

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

@ -1,47 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DebugTargetInfo component renders the expected snapshot for This Firefox target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel.thisFirefox-1.0.0
</b>
<span
className="devtools-ellipsis-text"
/>
</span>
<span
className="iconized-label"
>
<img
alt="favicon"
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component renders the expected snapshot for USB Release target 1`] = `
exports[`DebugTargetInfo component Connection info renders the expected snapshot for USB Release target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
@ -76,8 +35,8 @@ exports[`DebugTargetInfo component renders the expected snapshot for USB Release
className="iconized-label"
>
<img
alt="favicon"
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
alt="toolbox.debugTargetInfo.targetType.tab"
src="chrome://devtools/skin/images/globe.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
@ -93,7 +52,215 @@ exports[`DebugTargetInfo component renders the expected snapshot for USB Release
</header>
`;
exports[`DebugTargetInfo component renders the expected snapshot for a Toolbox with an unnamed target 1`] = `
exports[`DebugTargetInfo component Target icon renders the expected snapshot for a process target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label js-connection-info"
>
<img
alt="usb icon"
src="chrome://devtools/skin/images/aboutdebugging-usb-icon.svg"
/>
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel-usbRuntimeBrandName-1.0.0
</b>
<span
className="devtools-ellipsis-text"
>
usbDeviceName
</span>
</span>
<span
className="iconized-label"
>
<img
alt="toolbox.debugTargetInfo.targetType.process"
src="chrome://devtools/skin/images/settings.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component Target icon renders the expected snapshot for a tab target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label js-connection-info"
>
<img
alt="usb icon"
src="chrome://devtools/skin/images/aboutdebugging-usb-icon.svg"
/>
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel-usbRuntimeBrandName-1.0.0
</b>
<span
className="devtools-ellipsis-text"
>
usbDeviceName
</span>
</span>
<span
className="iconized-label"
>
<img
alt="toolbox.debugTargetInfo.targetType.tab"
src="chrome://devtools/skin/images/globe.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component Target icon renders the expected snapshot for a worker target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label js-connection-info"
>
<img
alt="usb icon"
src="chrome://devtools/skin/images/aboutdebugging-usb-icon.svg"
/>
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel-usbRuntimeBrandName-1.0.0
</b>
<span
className="devtools-ellipsis-text"
>
usbDeviceName
</span>
</span>
<span
className="iconized-label"
>
<img
alt="toolbox.debugTargetInfo.targetType.worker"
src="chrome://devtools/skin/images/debugging-workers.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component Target icon renders the expected snapshot for an extension target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label js-connection-info"
>
<img
alt="usb icon"
src="chrome://devtools/skin/images/aboutdebugging-usb-icon.svg"
/>
toolbox.debugTargetInfo.connection.usb
</span>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel-usbRuntimeBrandName-1.0.0
</b>
<span
className="devtools-ellipsis-text"
>
usbDeviceName
</span>
</span>
<span
className="iconized-label"
>
<img
alt="toolbox.debugTargetInfo.targetType.extension"
src="chrome://devtools/skin/images/debugging-addons.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component Target title renders the expected snapshot for This Firefox target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
@ -117,8 +284,49 @@ exports[`DebugTargetInfo component renders the expected snapshot for a Toolbox w
className="iconized-label"
>
<img
alt="favicon"
src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
alt="toolbox.debugTargetInfo.targetType.tab"
src="chrome://devtools/skin/images/globe.svg"
/>
<b
className="devtools-ellipsis-text js-target-title"
>
Test Tab Name
</b>
<span
className="devtools-ellipsis-text"
>
http://some.target/url
</span>
</span>
</header>
`;
exports[`DebugTargetInfo component Target title renders the expected snapshot for a Toolbox with an unnamed target 1`] = `
<header
className="debug-target-info js-debug-target-info"
>
<span
className="iconized-label"
>
<img
className="channel-icon"
src="chrome://devtools/skin/images/aboutdebugging-firefox-release.svg"
/>
<b
className="devtools-ellipsis-text"
>
toolbox.debugTargetInfo.runtimeLabel.thisFirefox-1.0.0
</b>
<span
className="devtools-ellipsis-text"
/>
</span>
<span
className="iconized-label"
>
<img
alt="toolbox.debugTargetInfo.targetType.tab"
src="chrome://devtools/skin/images/globe.svg"
/>
<span
className="devtools-ellipsis-text"

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

@ -10,7 +10,8 @@
const renderer = require("react-test-renderer");
const React = require("devtools/client/shared/vendor/react");
const DebugTargetInfo = React.createFactory(require("devtools/client/framework/components/DebugTargetInfo"));
const { CONNECTION_TYPES } = require("devtools/client/shared/remote-debugging/remote-client-manager");
const { CONNECTION_TYPES, DEBUG_TARGET_TYPES } =
require("devtools/client/shared/remote-debugging/constants");
/**
* Stub for the L10N property expected by the DebugTargetInfo component.
@ -41,7 +42,6 @@ const TEST_TOOLBOX_NO_NAME = {
const USB_DEVICE_DESCRIPTION = {
brandName: "usbRuntimeBrandName",
connectionType: CONNECTION_TYPES.USB,
channel: "release",
deviceName: "usbDeviceName",
version: "1.0.0",
@ -49,62 +49,109 @@ const USB_DEVICE_DESCRIPTION = {
const THIS_FIREFOX_DEVICE_DESCRIPTION = {
brandName: "thisFirefoxRuntimeBrandName",
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
channel: "release",
version: "1.0.0",
};
const USB_TARGET_INFO = DebugTargetInfo({
deviceDescription: USB_DEVICE_DESCRIPTION,
const USB_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.USB,
deviceDescription: USB_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX,
L10N: stubL10N,
});
};
const THIS_FIREFOX_TARGET_INFO = DebugTargetInfo({
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
const THIS_FIREFOX_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX,
L10N: stubL10N,
});
};
const THIS_FIREFOX_NO_NAME_TARGET_INFO = DebugTargetInfo({
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
const THIS_FIREFOX_NO_NAME_TARGET_INFO = {
debugTargetData: {
connectionType: CONNECTION_TYPES.THIS_FIREFOX,
deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
targetType: DEBUG_TARGET_TYPES.TAB,
},
toolbox: TEST_TOOLBOX_NO_NAME,
L10N: stubL10N,
});
};
describe("DebugTargetInfo component", () => {
it("displays connection info for USB Release target", () => {
const targetInfo = renderer.create(USB_TARGET_INFO);
expect(findByClassName(targetInfo.root, "js-connection-info").length).toEqual(1);
describe("Connection info", () => {
it("displays connection info for USB Release target", () => {
const component = renderer.create(DebugTargetInfo(USB_TARGET_INFO));
expect(findByClassName(component.root, "js-connection-info").length).toEqual(1);
});
it("renders the expected snapshot for USB Release target", () => {
const component = renderer.create(DebugTargetInfo(USB_TARGET_INFO));
expect(component.toJSON()).toMatchSnapshot();
});
it("hides the connection info for This Firefox target", () => {
const component = renderer.create(DebugTargetInfo(THIS_FIREFOX_TARGET_INFO));
expect(findByClassName(component.root, "js-connection-info").length).toEqual(0);
});
});
it("renders the expected snapshot for USB Release target", () => {
const targetInfo = renderer.create(USB_TARGET_INFO);
expect(targetInfo.toJSON()).toMatchSnapshot();
describe("Target title", () => {
it("displays the target title if the target of the Toolbox has a name", () => {
const component = renderer.create(DebugTargetInfo(THIS_FIREFOX_TARGET_INFO));
expect(findByClassName(component.root, "js-target-title").length).toEqual(1);
});
it("renders the expected snapshot for This Firefox target", () => {
const component = renderer.create(DebugTargetInfo(THIS_FIREFOX_TARGET_INFO));
expect(component.toJSON()).toMatchSnapshot();
});
it("doesn't display the target title if the target of the Toolbox has no name", () => {
const component = renderer.create(DebugTargetInfo(THIS_FIREFOX_NO_NAME_TARGET_INFO));
expect(findByClassName(component.root, "js-target-title").length).toEqual(0);
});
it("renders the expected snapshot for a Toolbox with an unnamed target", () => {
const component = renderer.create(DebugTargetInfo(THIS_FIREFOX_NO_NAME_TARGET_INFO));
expect(component.toJSON()).toMatchSnapshot();
});
});
it("hides the connection info for This Firefox target", () => {
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
expect(findByClassName(targetInfo.root, "js-connection-info").length).toEqual(0);
});
describe("Target icon", () => {
const buildProps = (base, extraDebugTargetData) => {
const props = Object.assign({}, base);
Object.assign(props.debugTargetData, extraDebugTargetData);
return props;
};
it("displays the target title if the target of the Toolbox has a name", () => {
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
expect(findByClassName(targetInfo.root, "js-target-title").length).toEqual(1);
});
it("renders the expected snapshot for a tab target", () => {
const props = buildProps(USB_TARGET_INFO, { targetType: DEBUG_TARGET_TYPES.TAB });
const component = renderer.create(DebugTargetInfo(props));
expect(component.toJSON()).toMatchSnapshot();
});
it("renders the expected snapshot for This Firefox target", () => {
const targetInfo = renderer.create(THIS_FIREFOX_TARGET_INFO);
expect(targetInfo.toJSON()).toMatchSnapshot();
});
it("renders the expected snapshot for a worker target", () => {
const props = buildProps(USB_TARGET_INFO, { targetType: DEBUG_TARGET_TYPES.WORKER });
const component = renderer.create(DebugTargetInfo(props));
expect(component.toJSON()).toMatchSnapshot();
});
it("doesn't display the target title if the target of the Toolbox has no name", () => {
const targetInfo = renderer.create(THIS_FIREFOX_NO_NAME_TARGET_INFO);
expect(findByClassName(targetInfo.root, "js-target-title").length).toEqual(0);
});
it("renders the expected snapshot for an extension target", () => {
const props = buildProps(USB_TARGET_INFO, { targetType: DEBUG_TARGET_TYPES.EXTENSION });
const component = renderer.create(DebugTargetInfo(props));
expect(component.toJSON()).toMatchSnapshot();
});
it("renders the expected snapshot for a Toolbox with an unnamed target", () => {
const targetInfo = renderer.create(THIS_FIREFOX_NO_NAME_TARGET_INFO);
expect(targetInfo.toJSON()).toMatchSnapshot();
it("renders the expected snapshot for a process target", () => {
const props = buildProps(USB_TARGET_INFO, { targetType: DEBUG_TARGET_TYPES.PROCESS });
const component = renderer.create(DebugTargetInfo(props));
expect(component.toJSON()).toMatchSnapshot();
});
});
});

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

@ -58,9 +58,7 @@ BottomHost.prototype = {
// Avoid resizing notification containers
this._splitter.setAttribute("resizebefore", "flex");
this.frame = ownerDocument.createXULElement("iframe");
this.frame.flex = 1; // Required to be able to shrink when the window shrinks
this.frame.className = "devtools-toolbox-bottom-iframe";
this.frame = createDevToolsFrame(ownerDocument, "devtools-toolbox-bottom-iframe");
this.frame.height = Math.min(
Services.prefs.getIntPref(this.heightPref),
this._browserContainer.clientHeight - MIN_PAGE_SIZE
@ -69,8 +67,6 @@ BottomHost.prototype = {
this._browserContainer.appendChild(this._splitter);
this._browserContainer.appendChild(this.frame);
this.frame.tooltip = "aHTMLTooltip";
// we have to load something so we can switch documents if we have to
this.frame.setAttribute("src", "about:blank");
@ -144,10 +140,7 @@ class SidebarHost {
this._splitter = ownerDocument.createXULElement("splitter");
this._splitter.setAttribute("class", "devtools-side-splitter");
this.frame = ownerDocument.createXULElement("iframe");
this.frame.flex = 1; // Required to be able to shrink when the window shrinks
this.frame.className = "devtools-toolbox-side-iframe";
this.frame = createDevToolsFrame(ownerDocument, "devtools-toolbox-side-iframe");
this.frame.width = Math.min(
Services.prefs.getIntPref(this.widthPref),
this._browserPanel.clientWidth - MIN_PAGE_SIZE
@ -167,7 +160,6 @@ class SidebarHost {
this._browserPanel.insertBefore(this._splitter, this._browserContainer);
}
this.frame.tooltip = "aHTMLTooltip";
this.frame.setAttribute("src", "about:blank");
const frame = await new Promise(resolve => {
@ -257,8 +249,15 @@ WindowHost.prototype = {
win.removeEventListener("load", frameLoad, true);
win.focus();
this.frame = win.document.getElementById("toolbox-iframe");
this.emit("ready", this.frame);
this.frame = createDevToolsFrame(win.document, "devtools-toolbox-window-iframe");
win.document.getElementById("devtools-toolbox-window").appendChild(this.frame);
// The forceOwnRefreshDriver attribute is set to avoid Windows only issues with
// CSS transitions when switching from docked to window hosts.
// Added in Bug 832920, should be reviewed in Bug 1542468.
this.frame.setAttribute("forceOwnRefreshDriver", "");
this.frame.setAttribute("src", "about:blank");
resolve(this.frame);
};
@ -408,6 +407,17 @@ function focusTab(tab) {
browserWindow.gBrowser.selectedTab = tab;
}
/**
* Create an iframe that can be used to load DevTools via about:devtools-toolbox.
*/
function createDevToolsFrame(doc, className) {
const frame = doc.createXULElement("iframe");
frame.flex = 1; // Required to be able to shrink when the window shrinks
frame.className = className;
frame.tooltip = "aHTMLTooltip";
return frame;
}
exports.Hosts = {
"bottom": BottomHost,
"left": LeftHost,

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

@ -14,5 +14,4 @@
width="900" height="320"
persist="screenX screenY width height sizemode">
<tooltip id="aHTMLTooltip" page="true"/>
<iframe id="toolbox-iframe" flex="1" forceOwnRefreshDriver="" tooltip="aHTMLTooltip"></iframe>
</window>

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

@ -71,6 +71,10 @@ loader.lazyGetter(this, "domNodeConstants", () => {
return require("devtools/shared/dom-node-constants");
});
loader.lazyGetter(this, "DEBUG_TARGET_TYPES", () => {
return require("devtools/client/shared/remote-debugging/constants").DEBUG_TARGET_TYPES;
});
loader.lazyGetter(this, "registerHarOverlay", () => {
return require("devtools/client/netmonitor/src/har/toolbox-overlay").register;
});
@ -213,7 +217,7 @@ function Toolbox(target, selectedTool, hostType, contentWindow, frameId,
*/
loader.lazyGetter(this, "direction", () => {
// Get the direction from browser.xul document
const top = this.win.top;
const top = this.topWindow;
const topDocEl = top.document.documentElement;
const isRtl = top.getComputedStyle(topDocEl).direction === "rtl";
return isRtl ? "rtl" : "ltr";
@ -377,6 +381,15 @@ Toolbox.prototype = {
return this._win;
},
/**
* When the toolbox is loaded in a frame with type="content", win.parent will not return
* the parent Chrome window. This getter should return the parent Chrome window
* regardless of the frame type. See Bug 1539979.
*/
get topWindow() {
return this.win.windowRoot.ownerGlobal;
},
/**
* Shortcut to the document containing the toolbox UI
*/
@ -440,11 +453,6 @@ Toolbox.prototype = {
*/
open: function() {
return (async function() {
this.browserRequire = BrowserLoader({
window: this.doc.defaultView,
useOnlyShared: true,
}).require;
const isToolboxURL = this.win.location.href.startsWith(this._URL);
if (isToolboxURL) {
// Update the URL so that onceDOMReady watch for the right url.
@ -454,9 +462,8 @@ Toolbox.prototype = {
if (this.hostType === Toolbox.HostType.PAGE) {
// Displays DebugTargetInfo which shows the basic information of debug target,
// if `about:devtools-toolbox` URL opens directly.
// DebugTargetInfo requires this._deviceDescription to be populated
this._showDebugTargetInfo = true;
this._deviceDescription = await this._getDeviceDescription();
// DebugTargetInfo requires this._debugTargetData to be populated
this._debugTargetData = await this._getDebugTargetData();
}
const domHelper = new DOMHelpers(this.win);
@ -484,6 +491,11 @@ Toolbox.prototype = {
this._threadClient = await attachThread(this);
await domReady;
this.browserRequire = BrowserLoader({
window: this.win,
useOnlyShared: true,
}).require;
// The web console is immediately loaded when replaying, so that the
// timeline will always be populated with generated messages.
if (this.target.isReplayEnabled()) {
@ -570,15 +582,14 @@ Toolbox.prototype = {
// Wait until the original tool is selected so that the split
// console input will receive focus.
const browserWin = this.win.top;
let splitConsolePromise = promise.resolve();
if (Services.prefs.getBoolPref(SPLITCONSOLE_ENABLED_PREF)) {
splitConsolePromise = this.openSplitConsole();
this.telemetry.addEventProperty(
browserWin, "open", "tools", null, "splitconsole", true);
this.win, "open", "tools", null, "splitconsole", true);
} else {
this.telemetry.addEventProperty(
browserWin, "open", "tools", null, "splitconsole", false);
this.win, "open", "tools", null, "splitconsole", false);
}
await promise.all([
@ -607,12 +618,22 @@ Toolbox.prototype = {
});
},
_getDeviceDescription: async function() {
_getDebugTargetData: async function() {
const url = new URL(this.win.location);
const searchParams = new this.win.URLSearchParams(url.search);
const targetType = searchParams.get("type") || DEBUG_TARGET_TYPES.TAB;
const deviceFront = await this.target.client.mainRoot.getFront("device");
const description = await deviceFront.getDescription();
const remoteId = new this.win.URLSearchParams(this.win.location.href).get("remoteId");
const deviceDescription = await deviceFront.getDescription();
const remoteId = searchParams.get("remoteId");
const connectionType = remoteClientManager.getConnectionTypeByRemoteId(remoteId);
return Object.assign({}, description, { connectionType });
return {
connectionType,
deviceDescription,
targetType,
};
},
_onTargetClosed: async function() {
@ -1165,12 +1186,12 @@ Toolbox.prototype = {
postMessage: function(msg) {
// We sometime try to send messages in middle of destroy(), where the
// toolbox iframe may already be detached and no longer have a parent.
if (this.win.parent) {
// toolbox iframe may already be detached.
if (!this._destroyer) {
// Toolbox document is still chrome and disallow identifying message
// origin via event.source as it is null. So use a custom id.
msg.frameId = this.frameId;
this.win.parent.postMessage(msg, "*");
this.topWindow.postMessage(msg, "*");
}
},
@ -1206,8 +1227,7 @@ Toolbox.prototype = {
closeToolbox: this.closeToolbox,
focusButton: this._onToolbarFocus,
toolbox: this,
showDebugTargetInfo: this._showDebugTargetInfo,
deviceDescription: this._deviceDescription,
debugTargetData: this._debugTargetData,
onTabsOrderUpdated: this._onTabsOrderUpdated,
});
@ -2112,8 +2132,7 @@ Toolbox.prototype = {
});
}
const browserWin = this.win.top;
this.telemetry.addEventProperties(browserWin, "open", "tools", null, {
this.telemetry.addEventProperties(this.win, "open", "tools", null, {
"width": width,
"session_id": this.sessionId,
});

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

@ -135,6 +135,7 @@ function Inspector(toolbox) {
this.onSidebarSelect = this.onSidebarSelect.bind(this);
this.onSidebarShown = this.onSidebarShown.bind(this);
this.onSidebarToggle = this.onSidebarToggle.bind(this);
this.handleThreadState = this.handleThreadState.bind(this);
this._target.on("will-navigate", this._onBeforeNavigate);
}
@ -155,8 +156,8 @@ Inspector.prototype = {
}
this._replayResumed = !dbg.isPaused();
this._onReplayPauseChange = this._onReplayPauseChange.bind(this);
this._target.on("pause-change", this._onReplayPauseChange);
this._target.threadClient.addListener("paused", this.handleThreadState);
this._target.threadClient.addListener("resumed", this.handleThreadState);
}
await Promise.all([
@ -1124,9 +1125,8 @@ Inspector.prototype = {
/**
* When replaying, reset the inspector whenever the target paused or unpauses.
*/
_onReplayPauseChange({ paused }) {
this._replayResumed = !paused;
handleThreadState(event) {
this._replayResumed = event != "paused";
this.onNewRoot();
},

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

@ -250,6 +250,14 @@ toolbox.debugTargetInfo.type.tab=tab
toolbox.debugTargetInfo.connection.usb=USB
toolbox.debugTargetInfo.connection.network=Network
# LOCALIZATION NOTE (toolbox.debugTargetInfo.targetType.*): This is displayed as the
# alt attribute for an icon in the toolbox header in about:devtools-toolbox,
# to indicate what is the type of the debug target being inspected.
toolbox.debugTargetInfo.targetType.extension=Extension
toolbox.debugTargetInfo.targetType.process=Process
toolbox.debugTargetInfo.targetType.tab=Tab
toolbox.debugTargetInfo.targetType.worker=Worker
# LOCALIZATION NOTE (browserToolbox.statusMessage): This is the label
# shown next to status details when the Browser Toolbox fails to connect or
# appears to be taking a while to do so.

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

@ -60,6 +60,14 @@ error_runtimeVersionTooOld=The connected runtime has an old version (%1$S). The
# Variable: runtime app version (looks like this 52.a3)
error_runtimeVersionTooOld67Debugger=The Debugger panel may not work with the connected runtime. Please use Firefox %S if you need to use the Debugger with this runtime.
# LOCALIZATION NOTE (error_webIDEDeprecated): Text for the deprecation message displayed when starting WebIDE.
error_webIDEDeprecated=WebIDE will be disabled in release 69. Remote debugging is now available in about:debugging.
# LOCALIZATION NOTE (notification_openAboutDebugging): Text for a button displayed in the deprecation message for WebIDE.
# Clicking on the button will open a tab on about:debugging.
notification_openAboutDebugging.label=Open about:debugging
notification_openAboutDebugging.accesskey=O
addons_stable=stable
addons_unstable=unstable
addons_install_button=install

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

@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const CONNECTION_TYPES = {
NETWORK: "network",
THIS_FIREFOX: "this-firefox",
UNKNOWN: "unknown",
USB: "usb",
};
const DEBUG_TARGET_TYPES = {
EXTENSION: "extension",
PROCESS: "process",
TAB: "tab",
WORKER: "worker",
};
module.exports = {
CONNECTION_TYPES,
DEBUG_TARGET_TYPES,
};

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

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'constants.js',
'remote-client-manager.js',
'version-checker.js',
)

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

@ -4,13 +4,7 @@
"use strict";
/* connection types for remote clients */
const CONNECTION_TYPES = {
NETWORK: "network",
THIS_FIREFOX: "this-firefox",
UNKNOWN: "unknown",
USB: "usb",
};
const { CONNECTION_TYPES } = require("devtools/client/shared/remote-debugging/constants");
/**
* This class is designed to be a singleton shared by all DevTools to get access to
@ -126,5 +120,4 @@ class RemoteClientManager {
// Expose a singleton of RemoteClientManager.
module.exports = {
remoteClientManager: new RemoteClientManager(),
CONNECTION_TYPES,
};

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

@ -38,6 +38,11 @@
border-inline-end: 1px solid var(--theme-splitter-color);
}
.debug-target-info .iconized-label img {
width: 20px;
height: 20px;
}
.debug-target-info img {
-moz-context-properties: fill;
fill: var(--theme-toolbar-icon-color);

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

@ -67,10 +67,17 @@ var UI = {
// toolbox session id.
this._telemetry.toolOpened("webide", -1, this);
this.notificationBox = new window.MozElements.NotificationBox(element => {
document.getElementById("containerbox")
.insertAdjacentElement("afterbegin", element);
});
function createNotificationBox() {
return new window.MozElements.NotificationBox(element => {
document.getElementById("containerbox")
.insertAdjacentElement("afterbegin", element);
});
}
// Create two distinct NotificationBox to be able to show the deprecation message and
// the error messages simultaneously.
this.notificationBox = createNotificationBox();
this.deprecationBox = createNotificationBox();
AppManager.init();
this.appManagerUpdate = this.appManagerUpdate.bind(this);
@ -108,6 +115,11 @@ var UI = {
this.contentViewer = window.docShell.contentViewer;
this.contentViewer.fullZoom = Services.prefs.getCharPref("devtools.webide.zoom");
// Show a deprecation message to encourage users to open the new Remote Debugging
if (Services.prefs.getBoolPref("devtools.webide.showDeprecationMessage", false)) {
this.showDeprecationMessage();
}
gDevToolsBrowser.isWebIDEInitialized.resolve();
},
@ -302,7 +314,24 @@ var UI = {
const nbox = this.notificationBox;
nbox.removeAllNotifications(true);
nbox.appendNotification(text, "webide:errornotification", null,
nbox.PRIORITY_WARNING_LOW, buttons);
nbox.PRIORITY_WARNING_LOW, buttons);
},
showDeprecationMessage: function() {
const text = Strings.GetStringFromName("error_webIDEDeprecated");
const buttons = [{
label: Strings.GetStringFromName("notification_openAboutDebugging.label"),
accessKey: Strings.GetStringFromName("notification_openAboutDebugging.accesskey"),
callback: function() {
const { openTrustedLink } = require("devtools/client/shared/link");
openTrustedLink("about:debugging");
},
}];
const nbox = this.deprecationBox;
nbox.removeAllNotifications(true);
nbox.appendNotification(text, "webide:deprecationnotification", null,
nbox.PRIORITY_WARNING_LOW, buttons);
},
dismissErrorNotification: function() {

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

@ -11,3 +11,6 @@ pref("devtools.webide.lastConnectedRuntime", "");
pref("devtools.webide.lastSelectedProject", "");
pref("devtools.webide.zoom", "1");
pref("devtools.webide.busyTimeout", 10000);
// Show a deprecation message when starting WebIDE.
pref("devtools.webide.showDeprecationMessage", true);

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

@ -33,6 +33,7 @@ skip-if = (os == "linux") # Bug 1024734
[test_runtime.html]
[test_manifestUpdate.html]
[test_addons.html]
[test_deprecation_message.html]
[test_device_runtime.html]
[test_autoconnect_runtime.html]
[test_autoselect_project.html]

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

@ -35,12 +35,14 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.webide.busyTimeout");
Services.prefs.clearUserPref("devtools.webide.lastSelectedProject");
Services.prefs.clearUserPref("devtools.webide.lastConnectedRuntime");
Services.prefs.clearUserPref("devtools.webide.showDeprecationMessage");
});
var openWebIDE = async function(autoInstallAddons) {
var openWebIDE = async function({ autoInstallAddons, showDeprecationMessage } = {}) {
info("opening WebIDE");
Services.prefs.setBoolPref("devtools.webide.autoinstallADBExtension", !!autoInstallAddons);
Services.prefs.setBoolPref("devtools.webide.showDeprecationMessage", !!showDeprecationMessage);
const win = Services.ww.openWindow(null, "chrome://webide/content/", "webide",
"chrome,centerscreen,resizable", null);
@ -220,3 +222,17 @@ function waitForConnectionChange(expectedState, count = 1) {
DebuggerServer.on("connectionchange", onConnectionChange);
});
}
/**
* Copied from shared-head.js.
*/
function waitUntil(predicate, interval = 100) {
if (predicate()) {
return Promise.resolve(true);
}
return new Promise(resolve => {
setTimeout(function() {
waitUntil(predicate, interval).then(() => resolve(true));
}, interval);
});
}

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

@ -47,7 +47,9 @@
(async function() {
ok(!isAdbAddonInstalled(), "ADB extension not installed");
const win = await openWebIDE(true);
const win = await openWebIDE({
autoInstallAddons: true,
});
// ADB is installed asynchronously after starting WebIDE.
while (!isAdbAddonInstalled()) {

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

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title></title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script>
<script type="application/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
</head>
<body>
<script type="application/javascript">
window.onload = function() {
SimpleTest.waitForExplicitFinish();
async function testWithMessageDisabled() {
info("Open WebIDE with the showDeprecationMessage preference set to FALSE");
const win = await openWebIDE({
showDeprecationMessage: false,
});
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
await gDevToolsBrowser.isWebIDEInitialized.promise;
ok(true, "WebIDE was initialized");
info("Check if the deprecation message is hidden");
const nbox = win.UI.deprecationBox;
const deprecationMessage = nbox.getNotificationWithValue("webide:deprecationnotification");
ok(!deprecationMessage, "The deprecation message is hidden");
await closeWebIDE(win);
}
async function testWithMessageEnabled() {
info("Open WebIDE with the showDeprecationMessage preference set to TRUE");
const win = await openWebIDE({
showDeprecationMessage: true,
});
const {gDevToolsBrowser} = require("devtools/client/framework/devtools-browser");
await gDevToolsBrowser.isWebIDEInitialized.promise;
ok(true, "WebIDE was initialized");
info("Check if the deprecation message is displayed");
const nbox = win.UI.deprecationBox;
const deprecationMessage = nbox.getNotificationWithValue("webide:deprecationnotification");
ok(!!deprecationMessage, "The deprecation message is displayed");
info("Check if a button is displayed in the notification box");
// Note: `notification-button` is a hardcoded className added by the XUL
// notificationbox widget and we cannot set custom classnames.
const button = nbox.stack.querySelector(".notification-button");
ok(!!button, "The button to open about:debugging is displayed");
button.click();
info("Wait until the about:debugging tab is selected in the main window");
const mainWindow = Services.wm.getMostRecentWindow("navigator:browser");
await waitUntil(() => {
const contentWindow = mainWindow.gBrowser.selectedBrowser.contentWindow;
return contentWindow.location.href.startsWith("about:debugging");
});
info("Remove the about:debugging tab");
await removeTab(mainWindow.gBrowser.selectedTab, mainWindow);
await closeWebIDE(win);
}
(async function() {
await testWithMessageDisabled();
await testWithMessageEnabled();
SimpleTest.finish();
})();
};
</script>
</body>
</html>

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

@ -119,3 +119,7 @@ skip-if = true # Bug 1220415
[browser_browsingContext-01.js]
[browser_browsingContext-02.js]
[browser_browsingContext-03.js]
[browser_csp_uir.js]
support-files =
file_csp_uir.html
file_csp_uir_dummy.html

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

@ -0,0 +1,58 @@
"use strict";
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
const TEST_URI = TEST_PATH + "file_csp_uir.html"; // important to be http: to test upgrade-insecure-requests
const RESULT_URI = TEST_PATH.replace("http://", "https://") + "file_csp_uir_dummy.html";
function verifyCSP(aTestName, aBrowser, aResultURI) {
return ContentTask.spawn(aBrowser, {aTestName, aResultURI}, async function({aTestName, aResultURI}) {
let channel = content.docShell.currentDocumentChannel;
is(channel.URI.asciiSpec, aResultURI, "testing CSP for " + aTestName);
});
}
add_task(async function test_csp_inheritance_regular_click() {
await BrowserTestUtils.withNewTab(TEST_URI, async function(browser) {
let loadPromise = BrowserTestUtils.browserLoaded(browser, false, RESULT_URI);
// set the data href + simulate click
BrowserTestUtils.synthesizeMouseAtCenter("#testlink", {},
gBrowser.selectedBrowser);
await loadPromise;
await verifyCSP("click()", gBrowser.selectedBrowser, RESULT_URI);
});
});
add_task(async function test_csp_inheritance_ctrl_click() {
await BrowserTestUtils.withNewTab(TEST_URI, async function(browser) {
let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, RESULT_URI);
// set the data href + simulate ctrl+click
BrowserTestUtils.synthesizeMouseAtCenter("#testlink",
{ ctrlKey: true, metaKey: true },
gBrowser.selectedBrowser);
let tab = await loadPromise;
gBrowser.selectTabAtIndex(2);
await verifyCSP("ctrl-click()", gBrowser.selectedBrowser, RESULT_URI);
await BrowserTestUtils.removeTab(tab);
});
});
add_task(async function test_csp_inheritance_right_click_open_link_in_new_tab() {
await BrowserTestUtils.withNewTab(TEST_URI, async function(browser) {
let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, RESULT_URI);
// set the data href + simulate right-click open link in tab
BrowserTestUtils.waitForEvent(document, "popupshown", false, event => {
// These are operations that must be executed synchronously with the event.
document.getElementById("context-openlinkintab").doCommand();
event.target.hidePopup();
return true;
});
BrowserTestUtils.synthesizeMouseAtCenter("#testlink",
{ type: "contextmenu", button: 2 },
gBrowser.selectedBrowser);
let tab = await loadPromise;
gBrowser.selectTabAtIndex(2);
await verifyCSP("right-click-open-in-new-tab()", gBrowser.selectedBrowser, RESULT_URI);
await BrowserTestUtils.removeTab(tab);
});
});

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1542858 - Test CSP upgrade-insecure-requests</title>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
</head>
<body>
<a id="testlink" href="file_csp_uir_dummy.html">testlink</a>
</body>
</html>

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

@ -0,0 +1 @@
<html><body>foo</body></html>

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

@ -5873,6 +5873,7 @@ nsresult nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal,
/* static */
nsresult nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
MOZ_ASSERT(NS_IsMainThread());
bool isBlobURL = false;
nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
@ -5923,6 +5924,69 @@ nsresult nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin) {
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetThreadSafeASCIIOrigin(nsIURI* aURI,
nsACString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
bool isBlobURL = false;
nsresult rv = aURI->SchemeIs(BLOBURI_SCHEME, &isBlobURL);
NS_ENSURE_SUCCESS(rv, rv);
// For Blob URI, the path is the URL of the owning page.
if (isBlobURL) {
nsAutoCString path;
rv = aURI->GetPathQueryRef(path);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURIOnAnyThread(getter_AddRefs(uri), path);
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
if (NS_FAILED(rv)) {
aOrigin.AssignLiteral("null");
return NS_OK;
}
return GetThreadSafeASCIIOrigin(uri, aOrigin);
}
aOrigin.Truncate();
// This is not supported yet.
nsCOMPtr<nsINestedURI> nestedURI(do_QueryInterface(aURI));
if (nestedURI) {
return NS_ERROR_UNKNOWN_PROTOCOL;
}
nsAutoCString host;
rv = aURI->GetAsciiHost(host);
if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
nsAutoCString userPass;
aURI->GetUserPass(userPass);
nsCOMPtr<nsIURI> uri = aURI;
nsAutoCString prePath;
if (!userPass.IsEmpty()) {
rv = NS_MutateURI(uri).SetUserPass(EmptyCString()).Finalize(uri);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = uri->GetPrePath(prePath);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin = prePath;
} else {
aOrigin.AssignLiteral("null");
}
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal,
nsAString& aOrigin) {
@ -5941,6 +6005,7 @@ nsresult nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal,
/* static */
nsresult nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin) {
MOZ_ASSERT(aURI, "missing uri");
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
@ -5964,6 +6029,24 @@ nsresult nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin) {
return NS_OK;
}
/* static */
nsresult nsContentUtils::GetThreadSafeUTFOrigin(nsIURI* aURI,
nsAString& aOrigin) {
#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
return NS_ERROR_UNKNOWN_PROTOCOL;
#endif
MOZ_ASSERT(aURI, "missing uri");
nsresult rv;
nsAutoCString asciiOrigin;
rv = GetThreadSafeASCIIOrigin(aURI, asciiOrigin);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin = NS_ConvertUTF8toUTF16(asciiOrigin);
return NS_OK;
}
/* static */
bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
nsIChannel* aChannel,

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

@ -2132,14 +2132,19 @@ class nsContentUtils {
* suitable for, for example, header values. The UTF versions return strings
* containing international characters.
*
* The thread-safe versions return NS_ERROR_UNKNOWN_PROTOCOL if the
* operation cannot be completed on the current thread.
*
* @pre aPrincipal/aOrigin must not be null.
*
* @note this should be used for HTML5 origin determination.
*/
static nsresult GetASCIIOrigin(nsIPrincipal* aPrincipal, nsACString& aOrigin);
static nsresult GetASCIIOrigin(nsIURI* aURI, nsACString& aOrigin);
static nsresult GetThreadSafeASCIIOrigin(nsIURI* aURI, nsACString& aOrigin);
static nsresult GetUTFOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin);
static nsresult GetUTFOrigin(nsIURI* aURI, nsAString& aOrigin);
static nsresult GetThreadSafeUTFOrigin(nsIURI* aURI, nsAString& aOrigin);
/**
* This method creates and dispatches "command" event, which implements

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

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("Core", "Embedding: APIs")
BUG_COMPONENT = ("Core", "User events and focus handling")
EXPORTS += [
'nsBaseCommandController.h',

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

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
with Files("**"):
BUG_COMPONENT = ("Core", "Geolocation")
BUG_COMPONENT = ("Core", "DOM: Geolocation")
EXPORTS += [
'nsGeoPosition.h',

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