зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
f2b514eaaa
|
@ -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.
|
||||
It’s 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.
|
||||
It’s 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',
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче