mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Merge m-c to graphics
MozReview-Commit-ID: LPeWBwbK82h
This commit is contained in:
commit
c65ab1c730
@ -8,6 +8,7 @@ module.exports = {
|
||||
"rules": {
|
||||
"mozilla/import-globals": "warn",
|
||||
"mozilla/no-import-into-var-and-global": "error",
|
||||
"mozilla/no-useless-parameters": "error",
|
||||
|
||||
// No (!foo in bar) or (!object instanceof Class)
|
||||
"no-unsafe-negation": "error",
|
||||
|
@ -32,7 +32,6 @@ function dumpAccessibleNode(aNode, level) {
|
||||
|
||||
|
||||
function dumpAccessibleTree(aNode, level) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
level = level || 0;
|
||||
|
||||
dumpAccessibleNode(aNode, level);
|
||||
@ -48,14 +47,12 @@ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
}
|
||||
|
||||
function A(o) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var acc = Components.classes['@mozilla.org/accessibilityService;1']
|
||||
.getService(Components.interfaces.nsIAccessibilityService);
|
||||
var acc = SpecialPowers.Cc['@mozilla.org/accessibilityService;1']
|
||||
.getService(SpecialPowers.Ci.nsIAccessibilityService);
|
||||
return acc.getAccessibleFor(o);
|
||||
}
|
||||
|
||||
function beginAccessible() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
dumpAccessibleTree(A(document),0);
|
||||
}
|
||||
setTimeout(beginAccessible, 100);
|
||||
|
@ -56,6 +56,6 @@ function destroy() {
|
||||
|
||||
// stop listening to preference changes
|
||||
let branch = prefTargetNS(this).branch;
|
||||
branch.removeObserver('', prefTargetNS(this).observer, false);
|
||||
branch.removeObserver('', prefTargetNS(this).observer);
|
||||
prefTargetNS(this).observer = null;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ exports.asyncWindowLeakTest = function*(assert, asyncTestFunc) {
|
||||
|
||||
// Stop tracking new windows and attempt to GC any resources allocated
|
||||
// by the test body.
|
||||
Services.obs.removeObserver(windowObserver, "domwindowopened", false);
|
||||
Services.obs.removeObserver(windowObserver, "domwindowopened");
|
||||
yield gc();
|
||||
|
||||
// Check to see if any of the windows we saw survived the GC. We consider
|
||||
|
@ -2,8 +2,8 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
||||
const { Services } = Cu.import('resource://gre/modules/Services.jsm');
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm');
|
||||
const { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm', {});
|
||||
|
||||
var processId;
|
||||
|
||||
|
@ -45,7 +45,7 @@ this.SafeMode = {
|
||||
return new Promise((aResolve, aReject) => {
|
||||
let observer = function(aSubject, aTopic, aData) {
|
||||
if (Services.prefs.getCharPref(kSafeModePref)) {
|
||||
Services.prefs.removeObserver(kSafeModePref, observer, false);
|
||||
Services.prefs.removeObserver(kSafeModePref, observer);
|
||||
aResolve();
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
var Cu = Components.utils;
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const { SystemAppProxy } = Cu.import("resource://gre/modules/SystemAppProxy.jsm");
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
const { SystemAppProxy } = Cu.import("resource://gre/modules/SystemAppProxy.jsm", {});
|
||||
|
||||
var eventHandler = function(evt) {
|
||||
if (!evt.detail || evt.detail.type !== "permission-prompt") {
|
||||
@ -33,4 +33,3 @@ addMessageListener("teardown", function() {
|
||||
addMessageListener("permission-response", function(detail) {
|
||||
SystemAppProxy._sendCustomEvent('mozContentEvent', detail);
|
||||
});
|
||||
|
||||
|
@ -9,8 +9,8 @@
|
||||
}
|
||||
|
||||
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm');
|
||||
const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm', {});
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm', {});
|
||||
|
||||
const manager = Cc["@mozilla.org/presentation-device/manager;1"]
|
||||
.getService(Ci.nsIPresentationDeviceManager);
|
||||
@ -91,4 +91,3 @@ addMessageListener('trigger-device-prompt', function(request_options) {
|
||||
addMessageListener('presentation-select-response', function(detail) {
|
||||
SystemAppProxy._sendCustomEvent('mozContentEvent', detail);
|
||||
});
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
'use strict';
|
||||
|
||||
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm');
|
||||
const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm', {});
|
||||
const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm', {});
|
||||
|
||||
const glue = Cc["@mozilla.org/presentation/requestuiglue;1"]
|
||||
.createInstance(Ci.nsIPresentationRequestUIGlue);
|
||||
|
@ -3,7 +3,7 @@ var Ci = Components.interfaces;
|
||||
|
||||
Cu.importGlobalProperties(['File']);
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
// Load a duplicated copy of the jsm to prevent messing with the currently running one
|
||||
var scope = {};
|
||||
|
@ -1,6 +1,6 @@
|
||||
var Cu = Components.utils;
|
||||
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
// Load a duplicated copy of the jsm to prevent messing with the currently running one
|
||||
var scope = {};
|
||||
|
@ -19,7 +19,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsManager",
|
||||
|
||||
// At end of test, restore original state
|
||||
const ORIGINAL_AUTH_URI = Services.prefs.getCharPref("identity.fxaccounts.auth.uri");
|
||||
var { SystemAppProxy } = Cu.import("resource://gre/modules/FxAccountsMgmtService.jsm");
|
||||
var { SystemAppProxy } = Cu.import("resource://gre/modules/FxAccountsMgmtService.jsm", {});
|
||||
const ORIGINAL_SENDCUSTOM = SystemAppProxy._sendCustomEvent;
|
||||
do_register_cleanup(function() {
|
||||
Services.prefs.setCharPref("identity.fxaccounts.auth.uri", ORIGINAL_AUTH_URI);
|
||||
@ -208,5 +208,3 @@ function httpd_setup (handlers, port=-1) {
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
|
@ -961,7 +961,6 @@ pref("security.sandbox.content.level", 2);
|
||||
pref("security.sandbox.content.level", 1);
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_STACKWALKING)
|
||||
// This controls the depth of stack trace that is logged when Windows sandbox
|
||||
// logging is turned on. This is only currently available for the content
|
||||
// process because the only other sandbox (for GMP) has too strict a policy to
|
||||
@ -969,7 +968,6 @@ pref("security.sandbox.content.level", 1);
|
||||
pref("security.sandbox.windows.log.stackTraceDepth", 0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
// This pref is discussed in bug 1083344, the naming is inspired from its
|
||||
|
@ -124,8 +124,8 @@ var DevEdition = {
|
||||
|
||||
uninit() {
|
||||
Services.prefs.removeObserver(this._devtoolsThemePrefName, this);
|
||||
Services.obs.removeObserver(this, "lightweight-theme-styling-update", false);
|
||||
Services.obs.removeObserver(this, "lightweight-theme-window-updated", false);
|
||||
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
|
||||
Services.obs.removeObserver(this, "lightweight-theme-window-updated");
|
||||
if (this.styleSheet) {
|
||||
this.styleSheet.removeEventListener("load", this);
|
||||
}
|
||||
|
@ -207,18 +207,12 @@ let gDecoderDoctorHandler = {
|
||||
}
|
||||
if (type == "adobe-cdm-not-activated" &&
|
||||
AppConstants.platform == "win") {
|
||||
if (!AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) {
|
||||
return gNavigatorBundle.getString("decoder.noCodecsVista.message");
|
||||
}
|
||||
return gNavigatorBundle.getString("decoder.noCodecs.message");
|
||||
}
|
||||
if (type == "platform-decoder-not-found") {
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "6.1")) {
|
||||
if (AppConstants.platform == "win") {
|
||||
return gNavigatorBundle.getString("decoder.noHWAcceleration.message");
|
||||
}
|
||||
if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) {
|
||||
return gNavigatorBundle.getString("decoder.noHWAccelerationVista.message");
|
||||
}
|
||||
if (AppConstants.platform == "linux") {
|
||||
return gNavigatorBundle.getString("decoder.noCodecsLinux.message");
|
||||
}
|
||||
|
@ -1412,7 +1412,7 @@ var BookmarkingUI = {
|
||||
if (event.target == event.currentTarget) {
|
||||
updatePlacesContextMenu(true);
|
||||
|
||||
Services.prefs.removeObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver, false);
|
||||
Services.prefs.removeObserver(this.RECENTLY_BOOKMARKED_PREF, prefObserver);
|
||||
PlacesUtils.bookmarks.removeObserver(this._recentlyBookmarkedObserver);
|
||||
this._recentlyBookmarkedObserver = null;
|
||||
if (placesContextMenu) {
|
||||
|
@ -137,15 +137,15 @@ var gSyncUI = {
|
||||
// Note that we don't show login errors in a notification bar here, but do
|
||||
// still need to track a login-failed state so the "Tools" menu updates
|
||||
// with the correct state.
|
||||
_loginFailed() {
|
||||
loginFailed() {
|
||||
// If Sync isn't already ready, we don't want to force it to initialize
|
||||
// by referencing Weave.Status - and it isn't going to be accurate before
|
||||
// Sync is ready anyway.
|
||||
if (!this.weaveService.ready) {
|
||||
this.log.debug("_loginFailed has sync not ready, so returning false");
|
||||
this.log.debug("loginFailed has sync not ready, so returning false");
|
||||
return false;
|
||||
}
|
||||
this.log.debug("_loginFailed has sync state=${sync}",
|
||||
this.log.debug("loginFailed has sync state=${sync}",
|
||||
{ sync: Weave.Status.login});
|
||||
return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
|
||||
},
|
||||
@ -163,7 +163,7 @@ var gSyncUI = {
|
||||
if (!gBrowser)
|
||||
return Promise.resolve();
|
||||
|
||||
let loginFailed = this._loginFailed();
|
||||
let loginFailed = this.loginFailed();
|
||||
|
||||
// Start off with a clean slate
|
||||
document.getElementById("sync-reauth-state").hidden = true;
|
||||
@ -266,7 +266,7 @@ var gSyncUI = {
|
||||
// via the UI.
|
||||
handleToolbarButton() {
|
||||
this._needsSetup().then(needsSetup => {
|
||||
if (needsSetup || this._loginFailed()) {
|
||||
if (needsSetup || this.loginFailed()) {
|
||||
this.openSetup();
|
||||
} else {
|
||||
this.doSync();
|
||||
@ -380,7 +380,7 @@ var gSyncUI = {
|
||||
|
||||
let needsSetup = yield this._needsSetup();
|
||||
let needsVerification = yield this._needsVerification();
|
||||
let loginFailed = this._loginFailed();
|
||||
let loginFailed = this.loginFailed();
|
||||
// This is a little messy as the Sync buttons are 1/2 Sync related and
|
||||
// 1/2 FxA related - so for some strings we use Sync strings, but for
|
||||
// others we reach into gFxAccounts for strings.
|
||||
|
@ -127,11 +127,6 @@ XPCOMUtils.defineLazyGetter(this, "gCustomizeMode", function() {
|
||||
return new scope.CustomizeMode(window);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function() {
|
||||
// Only show resizers on Windows 2000 and XP
|
||||
return AppConstants.isPlatformAndVersionAtMost("win", "5.9");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gPrefService", function() {
|
||||
return Services.prefs;
|
||||
});
|
||||
@ -3402,8 +3397,6 @@ var PrintPreviewListener = {
|
||||
this._chromeState.notificationsOpen = !notificationBox.notificationsHidden;
|
||||
notificationBox.notificationsHidden = true;
|
||||
|
||||
gBrowser.updateWindowResizers();
|
||||
|
||||
this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden;
|
||||
if (gFindBarInitialized)
|
||||
gFindBar.close();
|
||||
@ -5240,7 +5233,6 @@ function setToolbarVisibility(toolbar, isVisible, persist = true) {
|
||||
|
||||
PlacesToolbarHelper.init();
|
||||
BookmarkingUI.onToolbarVisibilityChange();
|
||||
gBrowser.updateWindowResizers();
|
||||
if (isVisible)
|
||||
ToolbarIconColor.inferFromText();
|
||||
}
|
||||
@ -7784,6 +7776,9 @@ var TabContextMenu = {
|
||||
for (let menuItem of menuItems)
|
||||
menuItem.disabled = disabled;
|
||||
|
||||
if (this.contextTab.hasAttribute("customizemode"))
|
||||
document.getElementById("context_openTabInWindow").disabled = true;
|
||||
|
||||
if (AppConstants.E10S_TESTING_ONLY) {
|
||||
menuItems = aPopupMenu.getElementsByAttribute("tbattr", "tabbrowser-remote");
|
||||
for (let menuItem of menuItems) {
|
||||
|
@ -474,6 +474,9 @@
|
||||
accesskey="&syncedTabs.context.copy.accesskey;"
|
||||
id="syncedTabsCopySelected"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&syncedTabs.context.openAllInTabs.label;"
|
||||
accesskey="&syncedTabs.context.openAllInTabs.accesskey;"
|
||||
id="syncedTabsOpenAllInTabs"/>
|
||||
<menuitem label="&syncSyncNowItem.label;"
|
||||
accesskey="&syncSyncNowItem.accesskey;"
|
||||
id="syncedTabsRefresh"/>
|
||||
@ -545,9 +548,7 @@
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
toolbarname="&menubarCmd.label;"
|
||||
accesskey="&menubarCmd.accesskey;"
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
autohide="true"
|
||||
#endif
|
||||
#endif
|
||||
context="toolbar-context-menu">
|
||||
<toolbaritem id="menubar-items" align="center">
|
||||
|
@ -215,18 +215,6 @@
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateWindowResizers">
|
||||
<body><![CDATA[
|
||||
if (!window.gShowPageResizers)
|
||||
return;
|
||||
|
||||
var show = window.windowState == window.STATE_NORMAL;
|
||||
for (let i = 0; i < this.browsers.length; i++) {
|
||||
this.browsers[i].showWindowResizer = show;
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_setCloseKeyState">
|
||||
<parameter name="aEnabled"/>
|
||||
<body><![CDATA[
|
||||
@ -538,9 +526,10 @@
|
||||
<parameter name="aBrowser"/>
|
||||
<parameter name="aStartsBlank"/>
|
||||
<parameter name="aWasPreloadedBrowser"/>
|
||||
<parameter name="aOrigStateFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
let stateFlags = 0;
|
||||
let stateFlags = aOrigStateFlags || 0;
|
||||
// Initialize mStateFlags to non-zero e.g. when creating a progress
|
||||
// listener for preloaded browsers as there was no progress listener
|
||||
// around when the content started loading. If the content didn't
|
||||
@ -1971,10 +1960,6 @@
|
||||
b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aParams.opener);
|
||||
}
|
||||
|
||||
if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
|
||||
b.setAttribute("showresizer", "true");
|
||||
}
|
||||
|
||||
if (!aParams.isPreloadBrowser && this.hasAttribute("autocompletepopup")) {
|
||||
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
||||
}
|
||||
@ -2839,6 +2824,9 @@
|
||||
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
|
||||
var isPending = aOtherTab.hasAttribute("pending");
|
||||
|
||||
let otherTabListener = remoteBrowser._tabListeners.get(aOtherTab);
|
||||
let stateFlags = otherTabListener.mStateFlags;
|
||||
|
||||
// Expedite the removal of the icon if it was already scheduled.
|
||||
if (aOtherTab._soundPlayingAttrRemovalTimer) {
|
||||
clearTimeout(aOtherTab._soundPlayingAttrRemovalTimer);
|
||||
@ -2896,7 +2884,7 @@
|
||||
this.mIsBusy = true;
|
||||
}
|
||||
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser, Ci.nsIBrowser.SWAP_DEFAULT);
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser, Ci.nsIBrowser.SWAP_DEFAULT, stateFlags);
|
||||
}
|
||||
|
||||
// Unregister the previously opened URI
|
||||
@ -2969,6 +2957,7 @@
|
||||
<parameter name="aOurTab"/>
|
||||
<parameter name="aOtherBrowser"/>
|
||||
<parameter name="aFlags"/>
|
||||
<parameter name="aStateFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Unhook our progress listener
|
||||
@ -3025,7 +3014,8 @@
|
||||
}
|
||||
|
||||
// Restore the progress listener
|
||||
tabListener = this.mTabProgressListener(aOurTab, ourBrowser, false, false);
|
||||
tabListener = this.mTabProgressListener(aOurTab, ourBrowser, false, false,
|
||||
aStateFlags);
|
||||
this._tabListeners.set(aOurTab, tabListener);
|
||||
|
||||
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
|
||||
@ -4963,7 +4953,6 @@
|
||||
this.appendChild(this._autoScrollPopup);
|
||||
this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
|
||||
this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink;
|
||||
this.updateWindowResizers();
|
||||
|
||||
// Hook up the event listeners to the first browser
|
||||
var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true, false);
|
||||
@ -5036,9 +5025,9 @@
|
||||
|
||||
<destructor>
|
||||
<![CDATA[
|
||||
Services.obs.removeObserver(this, "live-resize-start", false);
|
||||
Services.obs.removeObserver(this, "live-resize-end", false);
|
||||
Services.obs.removeObserver(this, "contextual-identity-updated", false);
|
||||
Services.obs.removeObserver(this, "live-resize-start");
|
||||
Services.obs.removeObserver(this, "live-resize-end");
|
||||
Services.obs.removeObserver(this, "contextual-identity-updated");
|
||||
|
||||
for (let tab of this.tabs) {
|
||||
let browser = tab.linkedBrowser;
|
||||
@ -6007,8 +5996,6 @@
|
||||
this._handleTabSelect();
|
||||
this.mTabstripWidth = width;
|
||||
}
|
||||
|
||||
this.tabbrowser.updateWindowResizers();
|
||||
break;
|
||||
case "mouseout":
|
||||
// If the "related target" (the node to which the pointer went) is not
|
||||
|
@ -52,7 +52,7 @@ function checkPage(data) {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
ok(!Services.io.offline, "After clicking the Try Again button, we're back " +
|
||||
"online.");
|
||||
Services.obs.removeObserver(observer, "network:offline-status-changed", false);
|
||||
Services.obs.removeObserver(observer, "network:offline-status-changed");
|
||||
finish();
|
||||
}, "network:offline-status-changed", false);
|
||||
|
||||
|
@ -10,7 +10,7 @@ const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts
|
||||
const PROGRESS_NOTIFICATION = "addon-progress";
|
||||
|
||||
const { REQUIRE_SIGNING } = Cu.import("resource://gre/modules/addons/AddonConstants.jsm", {});
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm");
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
var rootDir = getRootDirectory(gTestPath);
|
||||
var rootPath = rootDir.split('/');
|
||||
|
@ -10,15 +10,23 @@ const ID = "permissions@test.mozilla.org";
|
||||
|
||||
const DEFAULT_EXTENSION_ICON = "chrome://browser/content/extension.svg";
|
||||
|
||||
Services.perms.add(makeURI("https://example.com/"), "install",
|
||||
Services.perms.ALLOW_ACTION);
|
||||
|
||||
function promisePopupNotificationShown(name) {
|
||||
return new Promise(resolve => {
|
||||
PopupNotifications.panel.addEventListener("popupshown", () => {
|
||||
function popupshown() {
|
||||
let notification = PopupNotifications.getNotification(name);
|
||||
if (!notification) { return; }
|
||||
|
||||
ok(notification, `${name} notification shown`);
|
||||
ok(PopupNotifications.isPanelOpen, "notification panel open");
|
||||
|
||||
PopupNotifications.panel.removeEventListener("popupshown", popupshown);
|
||||
resolve(PopupNotifications.panel.firstChild);
|
||||
}, {once: true});
|
||||
}
|
||||
|
||||
PopupNotifications.panel.addEventListener("popupshown", popupshown);
|
||||
});
|
||||
}
|
||||
|
||||
@ -60,8 +68,14 @@ function checkNotification(panel, url) {
|
||||
|
||||
const INSTALL_FUNCTIONS = [
|
||||
function installMozAM(url) {
|
||||
return ContentTask.spawn(gBrowser.selectedBrowser, url, function*(cUrl) {
|
||||
return content.wrappedJSObject.installMozAM(cUrl);
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, url, function*(cUrl) {
|
||||
content.wrappedJSObject.installMozAM(cUrl);
|
||||
});
|
||||
},
|
||||
|
||||
function installTrigger(url) {
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, url, function*(cUrl) {
|
||||
content.wrappedJSObject.installTrigger(cUrl);
|
||||
});
|
||||
},
|
||||
];
|
||||
@ -78,7 +92,37 @@ add_task(function* () {
|
||||
function* runOnce(installFn, url, cancel) {
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
|
||||
|
||||
let installPromise = installFn(url);
|
||||
let installPromise = new Promise(resolve => {
|
||||
let listener = {
|
||||
onDownloadCancelled() {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(false);
|
||||
},
|
||||
|
||||
onDownloadFailed() {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(false);
|
||||
},
|
||||
|
||||
onInstallCancelled() {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(false);
|
||||
},
|
||||
|
||||
onInstallEnded() {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(true);
|
||||
},
|
||||
|
||||
onInstallFailed() {
|
||||
AddonManager.removeInstallListener(listener);
|
||||
resolve(false);
|
||||
},
|
||||
};
|
||||
AddonManager.addInstallListener(listener);
|
||||
});
|
||||
|
||||
installFn(url);
|
||||
|
||||
let panel = yield promisePopupNotificationShown("addon-webext-permissions");
|
||||
checkNotification(panel, url);
|
||||
@ -92,10 +136,10 @@ add_task(function* () {
|
||||
let result = yield installPromise;
|
||||
let addon = yield promiseGetAddonByID(ID);
|
||||
if (cancel) {
|
||||
is(result, "onInstallCancelled", "Installation was cancelled");
|
||||
ok(!result, "Installation was cancelled");
|
||||
is(addon, null, "Extension is not installed");
|
||||
} else {
|
||||
is(result, "onInstallEnded", "Installation completed");
|
||||
ok(result, "Installation completed");
|
||||
isnot(addon, null, "Extension is installed");
|
||||
addon.uninstall();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ var Downloads = (Components.utils.import("resource://gre/modules/Downloads.jsm",
|
||||
function promiseFormHistoryRemoved() {
|
||||
let deferred = Promise.defer();
|
||||
Services.obs.addObserver(function onfh() {
|
||||
Services.obs.removeObserver(onfh, "satchel-storage-changed", false);
|
||||
Services.obs.removeObserver(onfh, "satchel-storage-changed");
|
||||
deferred.resolve();
|
||||
}, "satchel-storage-changed", false);
|
||||
return deferred.promise;
|
||||
|
@ -177,3 +177,40 @@ add_task(function* test_dragging_adoption_events() {
|
||||
yield BrowserTestUtils.closeWindow(win1);
|
||||
yield BrowserTestUtils.closeWindow(win2);
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Tests that per-site zoom settings remain active after a tab is
|
||||
* dragged between windows.
|
||||
*/
|
||||
add_task(function* test_dragging_zoom_handling() {
|
||||
const ZOOM_FACTOR = 1.62;
|
||||
|
||||
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
let tab1 = yield BrowserTestUtils.openNewForegroundTab(win1.gBrowser);
|
||||
let tab2 = yield BrowserTestUtils.openNewForegroundTab(win2.gBrowser,
|
||||
"http://example.com/");
|
||||
|
||||
win2.FullZoom.setZoom(ZOOM_FACTOR);
|
||||
FullZoomHelper.zoomTest(tab2, ZOOM_FACTOR,
|
||||
"Original tab should have correct zoom factor");
|
||||
|
||||
let effect = EventUtils.synthesizeDrop(tab2, tab1,
|
||||
[[{type: TAB_DROP_TYPE, data: tab2}]],
|
||||
null, win2, win1);
|
||||
is(effect, "move", "Tab should be moved from win2 to win1.");
|
||||
|
||||
// Delay slightly to make sure we've finished executing any promise
|
||||
// chains in the zoom code.
|
||||
yield new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
FullZoomHelper.zoomTest(win1.gBrowser.selectedTab, ZOOM_FACTOR,
|
||||
"Dragged tab should have correct zoom factor");
|
||||
|
||||
win1.FullZoom.reset();
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win1);
|
||||
yield BrowserTestUtils.closeWindow(win2);
|
||||
});
|
||||
|
@ -7,19 +7,13 @@
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
function installMozAM(url) {
|
||||
return navigator.mozAddonManager.createInstall({url}).then(install => new Promise(resolve => {
|
||||
const EVENTS = [
|
||||
"onDownloadCancelled",
|
||||
"onDownloadFailed",
|
||||
"onInstallCancelled",
|
||||
"onInstallEnded",
|
||||
"onInstallFailed",
|
||||
];
|
||||
for (let event of EVENTS) {
|
||||
install.addEventListener(event, () => { resolve(event); });
|
||||
}
|
||||
return navigator.mozAddonManager.createInstall({url}).then(install => {
|
||||
install.install();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function installTrigger(url) {
|
||||
InstallTrigger.install({extension: url});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
@ -40,8 +40,8 @@ window.addEventListener("message", function(event) {
|
||||
getService(SpecialPowers.Ci.nsIPermissionManager);
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIIOService);
|
||||
var uri1 = ioService.newURI(frames.testFrame.location, null, null);
|
||||
var uri2 = ioService.newURI(frames.testFrame3.location, null, null);
|
||||
var uri1 = ioService.newURI(frames.testFrame.location);
|
||||
var uri2 = ioService.newURI(frames.testFrame3.location);
|
||||
|
||||
var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
|
||||
|
@ -44,6 +44,22 @@ var tests = [
|
||||
copyVal: "<e>xample.com",
|
||||
copyExpected: "e"
|
||||
},
|
||||
{
|
||||
copyVal: "<e>x<a>mple.com",
|
||||
copyExpected: "ea"
|
||||
},
|
||||
{
|
||||
copyVal: "<e><xa>mple.com",
|
||||
copyExpected: "exa"
|
||||
},
|
||||
{
|
||||
copyVal: "<e><xa>mple.co<m>",
|
||||
copyExpected: "exam"
|
||||
},
|
||||
{
|
||||
copyVal: "<e><xample.co><m>",
|
||||
copyExpected: "example.com"
|
||||
},
|
||||
|
||||
// pageproxystate="valid" from this point on (due to the load)
|
||||
{
|
||||
@ -63,6 +79,14 @@ var tests = [
|
||||
copyVal: "<e>xample.com",
|
||||
copyExpected: "e"
|
||||
},
|
||||
{
|
||||
copyVal: "<e>xample.co<m>",
|
||||
copyExpected: "em"
|
||||
},
|
||||
{
|
||||
copyVal: "<exam><ple.com>",
|
||||
copyExpected: "example.com"
|
||||
},
|
||||
|
||||
{
|
||||
loadURL: "http://example.com/foo",
|
||||
@ -200,15 +224,38 @@ function testCopy(copyVal, targetValue, cb) {
|
||||
waitForClipboard(targetValue, function() {
|
||||
gURLBar.focus();
|
||||
if (copyVal) {
|
||||
let startBracket = copyVal.indexOf("<");
|
||||
let endBracket = copyVal.indexOf(">");
|
||||
if (startBracket == -1 || endBracket == -1 ||
|
||||
startBracket > endBracket ||
|
||||
copyVal.replace("<", "").replace(">", "") != gURLBar.textValue) {
|
||||
let offsets = [];
|
||||
while (true) {
|
||||
let startBracket = copyVal.indexOf("<");
|
||||
let endBracket = copyVal.indexOf(">");
|
||||
if (startBracket == -1 && endBracket == -1) {
|
||||
break;
|
||||
}
|
||||
if (startBracket > endBracket || startBracket == -1) {
|
||||
offsets = [];
|
||||
break;
|
||||
}
|
||||
offsets.push([startBracket, endBracket - 1]);
|
||||
copyVal = copyVal.replace("<", "").replace(">", "");
|
||||
}
|
||||
if (offsets.length == 0 ||
|
||||
copyVal != gURLBar.textValue) {
|
||||
ok(false, "invalid copyVal: " + copyVal);
|
||||
}
|
||||
gURLBar.selectionStart = startBracket;
|
||||
gURLBar.selectionEnd = endBracket - 1;
|
||||
gURLBar.selectionStart = offsets[0][0];
|
||||
gURLBar.selectionEnd = offsets[0][1];
|
||||
if (offsets.length > 1) {
|
||||
let sel = gURLBar.editor.selection;
|
||||
let r0 = sel.getRangeAt(0);
|
||||
let node0 = r0.startContainer;
|
||||
sel.removeAllRanges();
|
||||
offsets.map(function(startEnd) {
|
||||
let range = r0.cloneRange();
|
||||
range.setStart(node0, startEnd[0]);
|
||||
range.setEnd(node0, startEnd[1]);
|
||||
sel.addRange(range);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
gURLBar.select();
|
||||
}
|
||||
|
@ -758,7 +758,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
<body><![CDATA[
|
||||
// Grab the actual input field's value, not our value, which could include moz-action:
|
||||
var inputVal = this.inputField.value;
|
||||
var selectedVal = inputVal.substring(this.selectionStart, this.selectionEnd);
|
||||
let selection = this.editor.selection;
|
||||
var selectedVal = selection.toString();
|
||||
|
||||
// Handle multiple-range selection as a string for simplicity.
|
||||
if (selection.rangeCount > 1) {
|
||||
return selectedVal;
|
||||
}
|
||||
|
||||
// If the selection doesn't start at the beginning or doesn't span the full domain or
|
||||
// the URL bar is modified or there is no text at all, nothing else to do here.
|
||||
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- -*- Mode: HTML -*- -->
|
||||
<!-- 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/. -->
|
||||
|
||||
<overlay id="win6-browser-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<toolbar id="toolbar-menubar"
|
||||
autohide="true"/>
|
||||
</overlay>
|
@ -6,9 +6,6 @@ browser.jar:
|
||||
#ifdef XP_MACOSX
|
||||
% overlay chrome://mozapps/content/update/updates.xul chrome://browser/content/softwareUpdateOverlay.xul
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
% overlay chrome://browser/content/browser.xul chrome://browser/content/win6BrowserOverlay.xul os=WINNT osversion>=6
|
||||
#endif
|
||||
% overlay chrome://global/content/viewSource.xul chrome://browser/content/viewSourceOverlay.xul
|
||||
% overlay chrome://global/content/viewPartialSource.xul chrome://browser/content/viewSourceOverlay.xul
|
||||
|
||||
@ -179,9 +176,6 @@ browser.jar:
|
||||
* content/browser/webrtcIndicator.xul (content/webrtcIndicator.xul)
|
||||
content/browser/webrtcIndicator.js (content/webrtcIndicator.js)
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
content/browser/win6BrowserOverlay.xul (content/win6BrowserOverlay.xul)
|
||||
#endif
|
||||
# the following files are browser-specific overrides
|
||||
* content/browser/license.html (/toolkit/content/license.html)
|
||||
% override chrome://global/content/license.html chrome://browser/content/license.html
|
||||
|
@ -26,15 +26,11 @@
|
||||
<label class="identity-popup-headline hostless" crop="end"/>
|
||||
</label>
|
||||
<description class="identity-popup-connection-not-secure"
|
||||
value="&identity.connectionNotSecure;"
|
||||
when-connection="not-secure secure-cert-user-overridden"/>
|
||||
when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>
|
||||
<description class="identity-popup-connection-secure"
|
||||
value="&identity.connectionSecure;"
|
||||
when-connection="secure secure-ev"/>
|
||||
<description value="&identity.connectionInternal;"
|
||||
when-connection="chrome"/>
|
||||
<description value="&identity.connectionFile;"
|
||||
when-connection="file"/>
|
||||
when-connection="secure secure-ev">&identity.connectionSecure;</description>
|
||||
<description when-connection="chrome">&identity.connectionInternal;</description>
|
||||
<description when-connection="file">&identity.connectionFile;</description>
|
||||
|
||||
<vbox id="identity-popup-security-descriptions">
|
||||
<description class="identity-popup-warning-gray"
|
||||
@ -105,11 +101,9 @@
|
||||
<label class="identity-popup-headline hostless" crop="end"/>
|
||||
</label>
|
||||
<description class="identity-popup-connection-not-secure"
|
||||
value="&identity.connectionNotSecure;"
|
||||
when-connection="not-secure secure-cert-user-overridden"/>
|
||||
when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>
|
||||
<description class="identity-popup-connection-secure"
|
||||
value="&identity.connectionSecure;"
|
||||
when-connection="secure secure-ev"/>
|
||||
when-connection="secure secure-ev">&identity.connectionSecure;</description>
|
||||
</vbox>
|
||||
|
||||
<vbox id="identity-popup-securityView-body" flex="1">
|
||||
|
@ -38,6 +38,7 @@ const kPrefCustomizationState = "browser.uiCustomization.state";
|
||||
const kPrefCustomizationAutoAdd = "browser.uiCustomization.autoAdd";
|
||||
const kPrefCustomizationDebug = "browser.uiCustomization.debug";
|
||||
const kPrefDrawInTitlebar = "browser.tabs.drawInTitlebar";
|
||||
const kPrefSelectedThemeID = "lightweightThemes.selectedThemeID";
|
||||
const kPrefWebIDEInNavbar = "devtools.webide.widget.inNavbarByDefault";
|
||||
|
||||
const kExpectedWindowURL = "chrome://browser/content/browser.xul";
|
||||
@ -262,24 +263,14 @@ var CustomizableUIInternal = {
|
||||
defaultCollapsed: false,
|
||||
}, true);
|
||||
|
||||
if (AppConstants.platform != "macosx") {
|
||||
if (AppConstants.MENUBAR_CAN_AUTOHIDE) {
|
||||
this.registerArea(CustomizableUI.AREA_MENUBAR, {
|
||||
legacy: true,
|
||||
type: CustomizableUI.TYPE_TOOLBAR,
|
||||
defaultPlacements: [
|
||||
"menubar-items",
|
||||
],
|
||||
get defaultCollapsed() {
|
||||
if (AppConstants.MENUBAR_CAN_AUTOHIDE) {
|
||||
if (AppConstants.platform == "linux") {
|
||||
return true;
|
||||
}
|
||||
// This is duplicated logic from /browser/base/jar.mn
|
||||
// for win6BrowserOverlay.xul.
|
||||
return AppConstants.isPlatformAndVersionAtLeast("win", 6);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
defaultCollapsed: true,
|
||||
}, true);
|
||||
}
|
||||
|
||||
@ -1930,15 +1921,7 @@ var CustomizableUIInternal = {
|
||||
// state immediately when a browser window opens, which is important for
|
||||
// other consumers of this API.
|
||||
loadSavedState() {
|
||||
let state = null;
|
||||
try {
|
||||
state = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
} catch (e) {
|
||||
log.debug("No saved state found");
|
||||
// This will fail if nothing has been customized, so silently fall back to
|
||||
// the defaults.
|
||||
}
|
||||
|
||||
let state = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
@ -2524,18 +2507,18 @@ var CustomizableUIInternal = {
|
||||
},
|
||||
|
||||
_resetUIState() {
|
||||
try {
|
||||
gUIStateBeforeReset.drawInTitlebar = Services.prefs.getBoolPref(kPrefDrawInTitlebar);
|
||||
gUIStateBeforeReset.uiCustomizationState = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
gUIStateBeforeReset.currentTheme = LightweightThemeManager.currentTheme;
|
||||
} catch (e) { }
|
||||
|
||||
this._resetExtraToolbars();
|
||||
|
||||
Services.prefs.clearUserPref(kPrefCustomizationState);
|
||||
gUIStateBeforeReset.selectedThemeID = Services.prefs.getCharPref(kPrefSelectedThemeID);
|
||||
let selectedThemeID = Services.prefs.getDefaultBranch("").getCharPref(kPrefSelectedThemeID);
|
||||
LightweightThemeManager.currentTheme =
|
||||
selectedThemeID ? LightweightThemeManager.getUsedTheme(selectedThemeID) : null;
|
||||
|
||||
gUIStateBeforeReset.drawInTitlebar = Services.prefs.getBoolPref(kPrefDrawInTitlebar);
|
||||
Services.prefs.clearUserPref(kPrefDrawInTitlebar);
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
log.debug("State reset");
|
||||
|
||||
gUIStateBeforeReset.uiCustomizationState = Services.prefs.getCharPref(kPrefCustomizationState);
|
||||
Services.prefs.clearUserPref(kPrefCustomizationState);
|
||||
|
||||
// Reset placements to make restoring default placements possible.
|
||||
gPlacements = new Map();
|
||||
@ -2603,7 +2586,7 @@ var CustomizableUIInternal = {
|
||||
|
||||
let uiCustomizationState = gUIStateBeforeReset.uiCustomizationState;
|
||||
let drawInTitlebar = gUIStateBeforeReset.drawInTitlebar;
|
||||
let currentTheme = gUIStateBeforeReset.currentTheme;
|
||||
let selectedThemeID = gUIStateBeforeReset.selectedThemeID;
|
||||
|
||||
// Need to clear the previous state before setting the prefs
|
||||
// because pref observers may check if there is a previous UI state.
|
||||
@ -2611,7 +2594,8 @@ var CustomizableUIInternal = {
|
||||
|
||||
Services.prefs.setCharPref(kPrefCustomizationState, uiCustomizationState);
|
||||
Services.prefs.setBoolPref(kPrefDrawInTitlebar, drawInTitlebar);
|
||||
LightweightThemeManager.currentTheme = currentTheme;
|
||||
LightweightThemeManager.currentTheme =
|
||||
selectedThemeID ? LightweightThemeManager.getUsedTheme(selectedThemeID) : null;
|
||||
this.loadSavedState();
|
||||
// If the user just customizes toolbar/titlebar visibility, gSavedState will be null
|
||||
// and we don't need to do anything else here:
|
||||
@ -2790,8 +2774,9 @@ var CustomizableUIInternal = {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LightweightThemeManager.currentTheme) {
|
||||
log.debug(LightweightThemeManager.currentTheme + " theme is non-default");
|
||||
if (Services.prefs.getDefaultBranch("").getCharPref(kPrefSelectedThemeID) !=
|
||||
Services.prefs.getCharPref(kPrefSelectedThemeID)) {
|
||||
log.debug(kPrefSelectedThemeID + " pref is non-default");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -449,7 +449,7 @@ CustomizeMode.prototype = {
|
||||
yield this._doTransition(false);
|
||||
this.removeLWTStyling();
|
||||
|
||||
Services.obs.removeObserver(this, "lightweight-theme-window-updated", false);
|
||||
Services.obs.removeObserver(this, "lightweight-theme-window-updated");
|
||||
|
||||
if (this.browser.selectedTab == gTab) {
|
||||
if (gTab.linkedBrowser.currentURI.spec == "about:blank") {
|
||||
|
@ -60,12 +60,12 @@ add_task(function*() {
|
||||
function promiseObserverNotification(aObserver) {
|
||||
let deferred = Promise.defer();
|
||||
function notificationCallback(e) {
|
||||
Services.obs.removeObserver(notificationCallback, aObserver, false);
|
||||
Services.obs.removeObserver(notificationCallback, aObserver);
|
||||
clearTimeout(timeoutId);
|
||||
deferred.resolve();
|
||||
}
|
||||
let timeoutId = setTimeout(() => {
|
||||
Services.obs.removeObserver(notificationCallback, aObserver, false);
|
||||
Services.obs.removeObserver(notificationCallback, aObserver);
|
||||
deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
|
||||
}, kTimeoutInMS);
|
||||
Services.obs.addObserver(notificationCallback, aObserver, false);
|
||||
|
@ -436,8 +436,8 @@ DistributionCustomizer.prototype = {
|
||||
value = value.replace(/%LOCALE%/g, this._locale);
|
||||
value = value.replace(/%LANGUAGE%/g, this._language);
|
||||
localizedStr.data = "data:text/plain," + key + "=" + value;
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
}
|
||||
defaults._prefBranch.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
|
||||
} catch (e) { /* ignore bad prefs and move on */ }
|
||||
}
|
||||
}
|
||||
|
@ -324,6 +324,7 @@ function MenuItem(extension, createProperties, isRoot = false) {
|
||||
|
||||
this.setDefaults();
|
||||
this.setProps(createProperties);
|
||||
|
||||
if (!this.hasOwnProperty("_id")) {
|
||||
this.id = gNextMenuItemID++;
|
||||
}
|
||||
@ -351,6 +352,12 @@ MenuItem.prototype = {
|
||||
if (createProperties.targetUrlPatterns != null) {
|
||||
this.targetUrlMatchPattern = new MatchPattern(this.targetUrlPatterns);
|
||||
}
|
||||
|
||||
// If a child MenuItem does not specify any contexts, then it should
|
||||
// inherit the contexts specified from its parent.
|
||||
if (createProperties.parentId && !createProperties.contexts) {
|
||||
this.contexts = this.parent.contexts;
|
||||
}
|
||||
},
|
||||
|
||||
setDefaults() {
|
||||
|
@ -11,7 +11,7 @@ var {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
||||
"resource:///modules/sessionstore/SessionStore.jsm");
|
||||
|
||||
const ssOnChangedTopic = "sessionstore-closed-objects-changed";
|
||||
const SS_ON_CLOSED_OBJECTS_CHANGED = "sessionstore-closed-objects-changed";
|
||||
|
||||
function getRecentlyClosed(maxResults, extension) {
|
||||
let recentlyClosed = [];
|
||||
@ -62,6 +62,7 @@ extensions.registerSchemaAPI("sessions", "addon_parent", context => {
|
||||
let maxResults = filter.maxResults == undefined ? this.MAX_SESSION_RESULTS : filter.maxResults;
|
||||
return Promise.resolve(getRecentlyClosed(maxResults, extension));
|
||||
},
|
||||
|
||||
restore: function(sessionId) {
|
||||
let session, closedId;
|
||||
if (sessionId) {
|
||||
@ -90,31 +91,15 @@ extensions.registerSchemaAPI("sessions", "addon_parent", context => {
|
||||
}
|
||||
return createSession(session, extension, closedId);
|
||||
},
|
||||
|
||||
onChanged: new SingletonEventManager(context, "sessions.onChanged", fire => {
|
||||
let listenerCount = 0;
|
||||
|
||||
let observer = {
|
||||
observe: function() {
|
||||
this.emit("changed");
|
||||
},
|
||||
};
|
||||
EventEmitter.decorate(observer);
|
||||
|
||||
let listener = (event) => {
|
||||
let observer = () => {
|
||||
context.runSafe(fire);
|
||||
};
|
||||
|
||||
observer.on("changed", listener);
|
||||
listenerCount++;
|
||||
if (listenerCount == 1) {
|
||||
Services.obs.addObserver(observer, ssOnChangedTopic, false);
|
||||
}
|
||||
Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED, false);
|
||||
return () => {
|
||||
observer.off("changed", listener);
|
||||
listenerCount -= 1;
|
||||
if (!listenerCount) {
|
||||
Services.obs.removeObserver(observer, ssOnChangedTopic);
|
||||
}
|
||||
Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
||||
};
|
||||
}).api(),
|
||||
},
|
||||
|
@ -710,6 +710,15 @@ ExtensionTabManager.prototype = {
|
||||
incognito: Boolean(tab.state && tab.state.isPrivate),
|
||||
};
|
||||
|
||||
if (this.hasTabPermission(tab)) {
|
||||
let entries = tab.state ? tab.state.entries : tab.entries;
|
||||
result.url = entries[0].url;
|
||||
result.title = entries[0].title;
|
||||
if (tab.image) {
|
||||
result.favIconUrl = tab.image;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
@ -63,6 +63,7 @@ support-files =
|
||||
[browser_ext_runtime_setUninstallURL.js]
|
||||
[browser_ext_sessions_getRecentlyClosed.js]
|
||||
[browser_ext_sessions_getRecentlyClosed_private.js]
|
||||
[browser_ext_sessions_getRecentlyClosed_tabs.js]
|
||||
[browser_ext_sessions_restore.js]
|
||||
[browser_ext_simple.js]
|
||||
[browser_ext_tab_runtimeConnect.js]
|
||||
|
@ -14,8 +14,8 @@ add_task(function* test_actionContextMenus() {
|
||||
const contexts = ["page_action", "browser_action"];
|
||||
|
||||
const parentId = browser.contextMenus.create({contexts, title: "parent"});
|
||||
await browser.contextMenus.create({contexts, parentId, title: "click A"});
|
||||
await browser.contextMenus.create({contexts, parentId, title: "click B"});
|
||||
await browser.contextMenus.create({parentId, title: "click A"});
|
||||
await browser.contextMenus.create({parentId, title: "click B"});
|
||||
|
||||
for (let i = 1; i < 9; i++) {
|
||||
await browser.contextMenus.create({contexts, title: `click ${i}`});
|
||||
@ -69,8 +69,11 @@ add_task(function* test_tabContextMenu() {
|
||||
permissions: ["contextMenus"],
|
||||
},
|
||||
async background() {
|
||||
await browser.contextMenus.create({title: "alpha", contexts: ["tab"]});
|
||||
await browser.contextMenus.create({title: "beta", contexts: ["tab"]});
|
||||
await browser.contextMenus.create({
|
||||
id: "alpha-beta-parent", title: "alpha-beta parent", contexts: ["tab"],
|
||||
});
|
||||
await browser.contextMenus.create({parentId: "alpha-beta-parent", title: "alpha"});
|
||||
await browser.contextMenus.create({parentId: "alpha-beta-parent", title: "beta"});
|
||||
|
||||
browser.contextMenus.onClicked.addListener((info, tab) => {
|
||||
browser.test.sendMessage("click", {info, tab});
|
||||
@ -103,7 +106,7 @@ add_task(function* test_tabContextMenu() {
|
||||
is(separator.tagName, "menuseparator", "Separator before first extension item");
|
||||
|
||||
is(submenu.tagName, "menu", "Correct submenu type");
|
||||
is(submenu.label, "Generated extension", "Correct submenu title");
|
||||
is(submenu.label, "alpha-beta parent", "Correct submenu title");
|
||||
|
||||
is(gamma.tagName, "menuitem", "Third menu item type is correct");
|
||||
is(gamma.label, "gamma", "Third menu item label is correct");
|
||||
|
@ -0,0 +1,96 @@
|
||||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
"use strict";
|
||||
|
||||
function expectedTabInfo(tab, window) {
|
||||
let browser = tab.linkedBrowser;
|
||||
return {
|
||||
url: browser.currentURI.spec,
|
||||
title: browser.contentTitle,
|
||||
favIconUrl: window.gBrowser.getIcon(tab),
|
||||
};
|
||||
}
|
||||
|
||||
function checkTabInfo(expected, actual) {
|
||||
for (let prop in expected) {
|
||||
is(actual[prop], expected[prop], `Expected value found for ${prop} of tab object.`);
|
||||
}
|
||||
}
|
||||
|
||||
add_task(async function test_sessions_get_recently_closed_tabs() {
|
||||
async function background() {
|
||||
browser.test.onMessage.addListener(async msg => {
|
||||
if (msg == "check-sessions") {
|
||||
let recentlyClosed = await browser.sessions.getRecentlyClosed();
|
||||
browser.test.sendMessage("recentlyClosed", recentlyClosed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
permissions: ["sessions", "tabs"],
|
||||
},
|
||||
background,
|
||||
});
|
||||
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await BrowserTestUtils.loadURI(win.gBrowser.selectedBrowser, "about:addons");
|
||||
await BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
|
||||
let expectedTabs = [];
|
||||
let tab = win.gBrowser.selectedTab;
|
||||
expectedTabs.push(expectedTabInfo(tab, win));
|
||||
|
||||
for (let url of ["about:robots", "about:mozilla"]) {
|
||||
tab = await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url);
|
||||
expectedTabs.push(expectedTabInfo(tab, win));
|
||||
}
|
||||
|
||||
await extension.startup();
|
||||
|
||||
// Test with a closed tab.
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
|
||||
extension.sendMessage("check-sessions");
|
||||
let recentlyClosed = await extension.awaitMessage("recentlyClosed");
|
||||
let tabInfo = recentlyClosed[0].tab;
|
||||
let expectedTab = expectedTabs.pop();
|
||||
checkTabInfo(expectedTab, tabInfo);
|
||||
|
||||
// Test with a closed window containing tabs.
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
||||
extension.sendMessage("check-sessions");
|
||||
recentlyClosed = await extension.awaitMessage("recentlyClosed");
|
||||
let tabInfos = recentlyClosed[0].window.tabs;
|
||||
is(tabInfos.length, 2, "Expected number of tabs in closed window.");
|
||||
for (let x = 0; x < tabInfos.length; x++) {
|
||||
checkTabInfo(expectedTabs[x], tabInfos[x]);
|
||||
}
|
||||
|
||||
await extension.unload();
|
||||
|
||||
// Test without tabs permission.
|
||||
extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
permissions: ["sessions"],
|
||||
},
|
||||
background,
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
extension.sendMessage("check-sessions");
|
||||
recentlyClosed = await extension.awaitMessage("recentlyClosed");
|
||||
tabInfos = recentlyClosed[0].window.tabs;
|
||||
is(tabInfos.length, 2, "Expected number of tabs in closed window.");
|
||||
for (let tabInfo of tabInfos) {
|
||||
for (let prop in expectedTabs[0]) {
|
||||
is(undefined,
|
||||
tabInfo[prop],
|
||||
`${prop} of tab object is undefined without tabs permission.`);
|
||||
}
|
||||
}
|
||||
|
||||
await extension.unload();
|
||||
});
|
@ -17,8 +17,8 @@
|
||||
* promiseContentDimensions alterContent
|
||||
*/
|
||||
|
||||
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
const {AppConstants} = Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
const {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm", {});
|
||||
|
||||
// We run tests under two different configurations, from browser.ini and
|
||||
// browser-remote.ini. When running from browser-remote.ini, the tests are
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
let eseBackStage = Cu.import("resource:///modules/ESEDBReader.jsm");
|
||||
let eseBackStage = Cu.import("resource:///modules/ESEDBReader.jsm", {});
|
||||
let ESE = eseBackStage.ESE;
|
||||
let KERNEL = eseBackStage.KERNEL;
|
||||
let gLibs = eseBackStage.gLibs;
|
||||
@ -468,4 +468,3 @@ add_task(function*() {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
let AutoMigrateBackstage = Cu.import("resource:///modules/AutoMigrate.jsm"); /* globals AutoMigrate */
|
||||
Cu.import("resource:///modules/AutoMigrate.jsm", this);
|
||||
|
||||
let gShimmedMigratorKeyPicker = null;
|
||||
let gShimmedMigrator = null;
|
||||
@ -11,6 +11,8 @@ const kUsecPerMin = 60 * 1000000;
|
||||
// we get in trouble because the object itself is frozen, and Proxies can't
|
||||
// return a different value to an object when directly proxying a frozen
|
||||
// object.
|
||||
let AutoMigrateBackstage = Cu.import("resource:///modules/AutoMigrate.jsm", {});
|
||||
|
||||
AutoMigrateBackstage.MigrationUtils = new Proxy({}, {
|
||||
get(target, name) {
|
||||
if (name == "getMigratorKeyForDefaultBrowser" && gShimmedMigratorKeyPicker) {
|
||||
@ -608,4 +610,3 @@ add_task(function* checkUndoVisitsState() {
|
||||
"1 unrelated.org visits should have persisted as it's not involved in the import.");
|
||||
yield PlacesTestUtils.clearHistory();
|
||||
});
|
||||
|
||||
|
@ -98,7 +98,7 @@ PrefsProvider.prototype = {
|
||||
|
||||
uninit() {
|
||||
for (let pref of gPrefsMap.keys()) {
|
||||
Services.prefs.removeObserver(pref, this, false);
|
||||
Services.prefs.removeObserver(pref, this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ SearchProvider.prototype = {
|
||||
|
||||
uninit() {
|
||||
try {
|
||||
Services.obs.removeObserver(this, CURRENT_ENGINE, true);
|
||||
Services.obs.removeObserver(this, CURRENT_ENGINE);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
const {OS} = Cu.import("resource://gre/modules/osfile.jsm");
|
||||
const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BackgroundPageThumbs",
|
||||
"resource://gre/modules/BackgroundPageThumbs.jsm");
|
||||
|
@ -439,8 +439,7 @@ BrowserGlue.prototype = {
|
||||
this._flashHangCount = 0;
|
||||
this._firstWindowReady = new Promise(resolve => this._firstWindowLoaded = resolve);
|
||||
|
||||
if (AppConstants.isPlatformAndVersionAtMost("win", "5.2") ||
|
||||
AppConstants.platform == "macosx") {
|
||||
if (AppConstants.platform == "macosx") {
|
||||
// Handles prompting to inform about incompatibilites when accessibility
|
||||
// and e10s are active together.
|
||||
E10SAccessibilityCheck.init();
|
||||
|
@ -42,7 +42,7 @@ function clearAllPlacesFavicons() {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "places-favicons-expired") {
|
||||
resolve();
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired", false);
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -102,7 +102,7 @@ function observeFavicon(aFirstPartyDomain, aExpectedCookie, aPageURI) {
|
||||
}
|
||||
|
||||
if (faviconReqXUL && faviconReqPlaces) {
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request", false);
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request");
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
@ -132,8 +132,8 @@ function waitOnFaviconResponse(aFaviconURL) {
|
||||
};
|
||||
|
||||
resolve(result);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-response", false);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-response");
|
||||
Services.obs.removeObserver(observer, "http-on-examine-cached-response");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ function clearAllPlacesFavicons() {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "places-favicons-expired") {
|
||||
resolve();
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired", false);
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -196,7 +196,7 @@ function* doTest(aTestPage, aFaviconHost, aFaviconURL) {
|
||||
// Waiting for favicon requests are all made.
|
||||
yield observer.promise;
|
||||
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request", false);
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request");
|
||||
|
||||
yield BrowserTestUtils.removeTab(tabInfo.tab);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ var gSearchPane = {
|
||||
|
||||
Services.obs.addObserver(this, "browser-search-engine-modified", false);
|
||||
window.addEventListener("unload", () => {
|
||||
Services.obs.removeObserver(this, "browser-search-engine-modified", false);
|
||||
Services.obs.removeObserver(this, "browser-search-engine-modified");
|
||||
});
|
||||
|
||||
this._initAutocomplete();
|
||||
|
@ -35,19 +35,43 @@ const mockOfflineAppCacheHelper = {
|
||||
|
||||
const mockSiteDataManager = {
|
||||
sites: new Map([
|
||||
[
|
||||
"https://account.xyz.com/",
|
||||
{
|
||||
usage: 1024 * 200,
|
||||
host: "account.xyz.com",
|
||||
status: Ci.nsIPermissionManager.ALLOW_ACTION
|
||||
}
|
||||
],
|
||||
[
|
||||
"https://shopping.xyz.com/",
|
||||
{
|
||||
usage: 102400,
|
||||
usage: 1024 * 100,
|
||||
host: "shopping.xyz.com",
|
||||
status: Ci.nsIPermissionManager.DENY_ACTION
|
||||
}
|
||||
],
|
||||
[
|
||||
"https://video.bar.com/",
|
||||
{
|
||||
usage: 1024 * 20,
|
||||
host: "video.bar.com",
|
||||
status: Ci.nsIPermissionManager.ALLOW_ACTION
|
||||
}
|
||||
],
|
||||
[
|
||||
"https://music.bar.com/",
|
||||
{
|
||||
usage: 10240,
|
||||
usage: 1024 * 10,
|
||||
host: "music.bar.com",
|
||||
status: Ci.nsIPermissionManager.DENY_ACTION
|
||||
}
|
||||
],
|
||||
[
|
||||
"https://books.foo.com/",
|
||||
{
|
||||
usage: 1024 * 2,
|
||||
host: "books.foo.com",
|
||||
status: Ci.nsIPermissionManager.ALLOW_ACTION
|
||||
}
|
||||
],
|
||||
@ -304,3 +328,49 @@ add_task(function* () {
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
yield SpecialPowers.pushPrefEnv({set: [["browser.storageManager.enabled", true]]});
|
||||
|
||||
mockSiteDataManager.register();
|
||||
let updatePromise = promiseSitesUpdated();
|
||||
yield openPreferencesViaOpenPreferencesAPI("advanced", "networkTab", { leaveOpen: true });
|
||||
yield updatePromise;
|
||||
|
||||
// Open the siteDataSettings subdialog
|
||||
let doc = gBrowser.selectedBrowser.contentDocument;
|
||||
let settingsBtn = doc.getElementById("siteDataSettings");
|
||||
let dialogOverlay = doc.getElementById("dialogOverlay");
|
||||
let dialogPromise = promiseLoadSubDialog("chrome://browser/content/preferences/siteDataSettings.xul");
|
||||
settingsBtn.doCommand();
|
||||
yield dialogPromise;
|
||||
is(dialogOverlay.style.visibility, "visible", "The dialog should be visible");
|
||||
|
||||
let frameDoc = doc.getElementById("dialogFrame").contentDocument;
|
||||
let searchBox = frameDoc.getElementById("searchBox");
|
||||
let mockOrigins = Array.from(mockSiteDataManager.sites.keys());
|
||||
|
||||
searchBox.value = "xyz";
|
||||
searchBox.doCommand();
|
||||
assertSitesListed(mockOrigins.filter(o => o.includes("xyz")));
|
||||
|
||||
searchBox.value = "bar";
|
||||
searchBox.doCommand();
|
||||
assertSitesListed(mockOrigins.filter(o => o.includes("bar")));
|
||||
|
||||
searchBox.value = "";
|
||||
searchBox.doCommand();
|
||||
assertSitesListed(mockOrigins);
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
function assertSitesListed(origins) {
|
||||
let sitesList = frameDoc.getElementById("sitesList");
|
||||
let totalSitesNumber = sitesList.getElementsByTagName("richlistitem").length;
|
||||
is(totalSitesNumber, origins.length, "Should list the right sites number");
|
||||
origins.forEach(origin => {
|
||||
let site = sitesList.querySelector(`richlistitem[data-origin="${origin}"]`);
|
||||
ok(site instanceof XULElement, `Should list the site of ${origin}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -2,6 +2,10 @@
|
||||
* 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/. */
|
||||
|
||||
#searchBoxContainer {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#sitesList {
|
||||
min-height: 20em;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ let gSiteDataSettings = {
|
||||
_sites: null,
|
||||
|
||||
_list: null,
|
||||
_searchBox: null,
|
||||
|
||||
init() {
|
||||
function setEventListener(id, eventType, callback) {
|
||||
@ -31,6 +32,7 @@ let gSiteDataSettings = {
|
||||
}
|
||||
|
||||
this._list = document.getElementById("sitesList");
|
||||
this._searchBox = document.getElementById("searchBox");
|
||||
SiteDataManager.getSites().then(sites => {
|
||||
this._sites = sites;
|
||||
let sortCol = document.getElementById("hostCol");
|
||||
@ -41,6 +43,7 @@ let gSiteDataSettings = {
|
||||
setEventListener("hostCol", "click", this.onClickTreeCol);
|
||||
setEventListener("usageCol", "click", this.onClickTreeCol);
|
||||
setEventListener("statusCol", "click", this.onClickTreeCol);
|
||||
setEventListener("searchBox", "command", this.onCommandSearch);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -89,19 +92,29 @@ let gSiteDataSettings = {
|
||||
col.setAttribute("data-last-sortDirection", sortDirection);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param sites {Array} array of metadata of sites
|
||||
*/
|
||||
_buildSitesList(sites) {
|
||||
// Clear old entries.
|
||||
while (this._list.childNodes.length > 1) {
|
||||
this._list.removeChild(this._list.lastChild);
|
||||
let oldItems = this._list.querySelectorAll("richlistitem");
|
||||
for (let item of oldItems) {
|
||||
item.remove();
|
||||
}
|
||||
|
||||
let prefStrBundle = document.getElementById("bundlePreferences");
|
||||
let keyword = this._searchBox.value.toLowerCase().trim();
|
||||
for (let data of sites) {
|
||||
let host = data.uri.host;
|
||||
if (keyword && !host.includes(keyword)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let statusStrId = data.status === Ci.nsIPermissionManager.ALLOW_ACTION ? "important" : "default";
|
||||
let size = DownloadUtils.convertByteUnits(data.usage);
|
||||
let item = document.createElement("richlistitem");
|
||||
item.setAttribute("data-origin", data.uri.spec);
|
||||
item.setAttribute("host", data.uri.host);
|
||||
item.setAttribute("host", host);
|
||||
item.setAttribute("status", prefStrBundle.getString(statusStrId));
|
||||
item.setAttribute("usage", prefStrBundle.getFormattedString("siteUsage", size));
|
||||
this._list.appendChild(item);
|
||||
@ -111,5 +124,9 @@ let gSiteDataSettings = {
|
||||
onClickTreeCol(e) {
|
||||
this._sortSites(this._sites, e.target);
|
||||
this._buildSitesList(this._sites);
|
||||
},
|
||||
|
||||
onCommandSearch() {
|
||||
this._buildSitesList(this._sites);
|
||||
}
|
||||
};
|
||||
|
@ -26,6 +26,12 @@
|
||||
<description>&settings.description;</description>
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox id="searchBoxContainer">
|
||||
<label accesskey="&search.accesskey;" control="searchBox">&search.label;</label>
|
||||
<textbox id="searchBox" type="search" flex="1"/>
|
||||
</hbox>
|
||||
<separator class="thin"/>
|
||||
|
||||
<richlistbox id="sitesList" orient="vertical" flex="1">
|
||||
<listheader>
|
||||
<treecol flex="4" width="50" label="&hostCol.label;" id="hostCol"/>
|
||||
|
@ -35,7 +35,7 @@ function clearAllPlacesFavicons() {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic === "places-favicons-expired") {
|
||||
resolve();
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired", false);
|
||||
Services.obs.removeObserver(observer, "places-favicons-expired");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -105,7 +105,7 @@ function observeFavicon(aIsPrivate, aExpectedCookie, aPageURI) {
|
||||
|
||||
if (faviconReqXUL && faviconReqPlaces) {
|
||||
resolve();
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request", false);
|
||||
Services.obs.removeObserver(observer, "http-on-modify-request");
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -134,8 +134,8 @@ function waitOnFaviconResponse(aFaviconURL) {
|
||||
};
|
||||
|
||||
resolve(result);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-response", false);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-cached-response", false);
|
||||
Services.obs.removeObserver(observer, "http-on-examine-response");
|
||||
Services.obs.removeObserver(observer, "http-on-examine-cached-response");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -51,6 +51,20 @@ function promiseEvent(aTarget, aEventName, aPreventDefault) {
|
||||
return BrowserTestUtils.waitForEvent(aTarget, aEventName, false, cancelEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new search engine to the search service and confirms it completes.
|
||||
*
|
||||
* @param {String} basename The file to load that contains the search engine
|
||||
* details.
|
||||
* @param {Object} [options] Options for the test:
|
||||
* - {String} [iconURL] The icon to use for the search engine.
|
||||
* - {Boolean} [setAsCurrent] Whether to set the new engine to be the
|
||||
* current engine or not.
|
||||
* - {String} [testPath] Used to override the current test path if this
|
||||
* file is used from a different directory.
|
||||
* @returns {Promise} The promise is resolved once the engine is added, or
|
||||
* rejected if the addition failed.
|
||||
*/
|
||||
function promiseNewEngine(basename, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Default the setAsCurrent option to true.
|
||||
@ -59,7 +73,7 @@ function promiseNewEngine(basename, options = {}) {
|
||||
info("Waiting for engine to be added: " + basename);
|
||||
Services.search.init({
|
||||
onInitComplete() {
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
let url = getRootDirectory(options.testPath || gTestPath) + basename;
|
||||
let current = Services.search.currentEngine;
|
||||
Services.search.addEngine(url, null, options.iconURL || "", false, {
|
||||
onSuccess(engine) {
|
||||
|
@ -3613,7 +3613,7 @@ var SessionStoreInternal = {
|
||||
* true if we want to reload into a fresh process
|
||||
*/
|
||||
restoreTabContent: function (aTab, aLoadArguments = null, aReloadInFreshProcess = false) {
|
||||
if (aTab.hasAttribute("customizemode")) {
|
||||
if (aTab.hasAttribute("customizemode") && !aLoadArguments) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ SyncedTabsDeckComponent.prototype = {
|
||||
init() {
|
||||
Services.obs.addObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED, false);
|
||||
Services.obs.addObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION, false);
|
||||
Services.obs.addObserver(this, "weave:service:login:change", false);
|
||||
|
||||
// Go ahead and trigger sync
|
||||
this._SyncedTabs.syncTabs()
|
||||
@ -94,6 +95,7 @@ SyncedTabsDeckComponent.prototype = {
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, this._SyncedTabs.TOPIC_TABS_CHANGED);
|
||||
Services.obs.removeObserver(this, FxAccountsCommon.ONLOGIN_NOTIFICATION);
|
||||
Services.obs.removeObserver(this, "weave:service:login:change");
|
||||
this._deckView.destroy();
|
||||
},
|
||||
|
||||
@ -104,6 +106,7 @@ SyncedTabsDeckComponent.prototype = {
|
||||
this.updatePanel();
|
||||
break;
|
||||
case FxAccountsCommon.ONLOGIN_NOTIFICATION:
|
||||
case "weave:service:login:change":
|
||||
this.updatePanel();
|
||||
break;
|
||||
default:
|
||||
@ -119,7 +122,7 @@ SyncedTabsDeckComponent.prototype = {
|
||||
|
||||
getPanelStatus() {
|
||||
return this._accountStatus().then(exists => {
|
||||
if (!exists) {
|
||||
if (!exists || this._getChromeWindow(this._window).gSyncUI.loginFailed()) {
|
||||
return this.PANELS.NOT_AUTHED_INFO;
|
||||
}
|
||||
if (!this._SyncedTabs.isConfiguredToSyncTabs) {
|
||||
|
@ -287,9 +287,7 @@ TabListView.prototype = {
|
||||
if (itemNode.classList.contains("client")) {
|
||||
let where = getChromeWindow(this._window).whereToOpenLink(event);
|
||||
if (where != "current") {
|
||||
const tabs = itemNode.querySelector(".item-tabs-list").childNodes;
|
||||
const urls = [...tabs].map(tab => tab.dataset.url);
|
||||
this.props.onOpenTabs(urls, where);
|
||||
this._openAllClientTabs(itemNode, where);
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,6 +353,13 @@ TabListView.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
onOpenAllInTabs() {
|
||||
let item = this._getSelectedClientNode();
|
||||
if (item) {
|
||||
this._openAllClientTabs(item, "tab");
|
||||
}
|
||||
},
|
||||
|
||||
onFilter(event) {
|
||||
let query = event.target.value;
|
||||
if (query) {
|
||||
@ -383,6 +388,14 @@ TabListView.prototype = {
|
||||
return null;
|
||||
},
|
||||
|
||||
_getSelectedClientNode() {
|
||||
let item = this.container.querySelector('.item.selected');
|
||||
if (this._isClient(item)) {
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Set up the custom context menu
|
||||
_setupContextMenu() {
|
||||
Services.els.addSystemEventListener(this._window, "contextmenu", this, false);
|
||||
@ -461,6 +474,9 @@ TabListView.prototype = {
|
||||
case "syncedTabsOpenSelectedInPrivateWindow":
|
||||
this.onOpenSelectedFromContextMenu(event);
|
||||
break;
|
||||
case "syncedTabsOpenAllInTabs":
|
||||
this.onOpenAllInTabs();
|
||||
break;
|
||||
case "syncedTabsBookmarkSelected":
|
||||
this.onBookmarkTab();
|
||||
break;
|
||||
@ -506,11 +522,18 @@ TabListView.prototype = {
|
||||
let el = menu.firstChild;
|
||||
|
||||
while (el) {
|
||||
if (showTabOptions || el.getAttribute("id") === "syncedTabsRefresh") {
|
||||
el.hidden = false;
|
||||
} else {
|
||||
el.hidden = true;
|
||||
let show = false;
|
||||
if (showTabOptions) {
|
||||
if (el.getAttribute("id") != "syncedTabsOpenAllInTabs") {
|
||||
show = true;
|
||||
}
|
||||
} else if (el.getAttribute("id") == "syncedTabsOpenAllInTabs") {
|
||||
const tabs = item.querySelectorAll(".item-tabs-list > .item.tab");
|
||||
show = tabs.length > 0;
|
||||
} else if (el.getAttribute("id") == "syncedTabsRefresh") {
|
||||
show = true;
|
||||
}
|
||||
el.hidden = !show;
|
||||
|
||||
el = el.nextSibling;
|
||||
}
|
||||
@ -564,5 +587,15 @@ TabListView.prototype = {
|
||||
|
||||
_isTab(item) {
|
||||
return item && item.classList.contains("tab");
|
||||
},
|
||||
|
||||
_isClient(item) {
|
||||
return item && item.classList.contains("client");
|
||||
},
|
||||
|
||||
_openAllClientTabs(clientNode, where) {
|
||||
const tabs = clientNode.querySelector(".item-tabs-list").childNodes;
|
||||
const urls = [...tabs].map(tab => tab.dataset.url);
|
||||
this.props.onOpenTabs(urls, where);
|
||||
}
|
||||
};
|
||||
|
@ -310,6 +310,7 @@ add_task(function* testSyncedTabsSidebarContextMenu() {
|
||||
["menuitem#syncedTabsBookmarkSelected", { hidden: false }],
|
||||
["menuitem#syncedTabsCopySelected", { hidden: false }],
|
||||
["menuseparator", { hidden: false }],
|
||||
["menuitem#syncedTabsOpenAllInTabs", { hidden: true }],
|
||||
["menuitem#syncedTabsRefresh", { hidden: false }],
|
||||
];
|
||||
yield* testContextMenu(syncedTabsDeckComponent,
|
||||
@ -317,7 +318,7 @@ add_task(function* testSyncedTabsSidebarContextMenu() {
|
||||
"#tab-7cqCr77ptzX3-0",
|
||||
tabMenuItems);
|
||||
|
||||
info("Right-clicking a client shouldn't show any actions");
|
||||
info("Right-clicking a client should show the Open All in Tabs action");
|
||||
let sidebarMenuItems = [
|
||||
["menuitem#syncedTabsOpenSelected", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenSelectedInTab", { hidden: true }],
|
||||
@ -327,12 +328,31 @@ add_task(function* testSyncedTabsSidebarContextMenu() {
|
||||
["menuitem#syncedTabsBookmarkSelected", { hidden: true }],
|
||||
["menuitem#syncedTabsCopySelected", { hidden: true }],
|
||||
["menuseparator", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenAllInTabs", { hidden: false }],
|
||||
["menuitem#syncedTabsRefresh", { hidden: false }],
|
||||
];
|
||||
yield* testContextMenu(syncedTabsDeckComponent,
|
||||
"#SyncedTabsSidebarContext",
|
||||
"#item-7cqCr77ptzX3",
|
||||
sidebarMenuItems);
|
||||
|
||||
info("Right-clicking a client without any tabs should not show the Open All in Tabs action");
|
||||
let menuItems = [
|
||||
["menuitem#syncedTabsOpenSelected", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenSelectedInTab", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenSelectedInWindow", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenSelectedInPrivateWindow", { hidden: true }],
|
||||
["menuseparator", { hidden: true }],
|
||||
["menuitem#syncedTabsBookmarkSelected", { hidden: true }],
|
||||
["menuitem#syncedTabsCopySelected", { hidden: true }],
|
||||
["menuseparator", { hidden: true }],
|
||||
["menuitem#syncedTabsOpenAllInTabs", { hidden: true }],
|
||||
["menuitem#syncedTabsRefresh", { hidden: false }],
|
||||
];
|
||||
yield* testContextMenu(syncedTabsDeckComponent,
|
||||
"#SyncedTabsSidebarContext",
|
||||
"#item-OL3EJCsdb2JD",
|
||||
sidebarMenuItems);
|
||||
menuItems);
|
||||
});
|
||||
|
||||
add_task(testClean);
|
||||
|
@ -122,6 +122,12 @@ add_task(function* testObserver() {
|
||||
Assert.ok(component.observe.calledWith(null, FxAccountsCommon.ONLOGIN_NOTIFICATION, ""),
|
||||
"component is notified of login");
|
||||
Assert.equal(component.updatePanel.callCount, 3, "triggers panel update again");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:service:login:change", "");
|
||||
|
||||
Assert.ok(component.observe.calledWith(null, "weave:service:login:change", ""),
|
||||
"component is notified of login change");
|
||||
Assert.equal(component.updatePanel.callCount, 4, "triggers panel update again");
|
||||
});
|
||||
|
||||
add_task(function* testPanelStatus() {
|
||||
@ -134,6 +140,16 @@ add_task(function* testPanelStatus() {
|
||||
let SyncedTabsMock = {
|
||||
getTabClients() {}
|
||||
};
|
||||
let loginFailed = false;
|
||||
let chromeWindowMock = {
|
||||
gSyncUI: {
|
||||
loginFailed() {
|
||||
return loginFailed;
|
||||
}
|
||||
}
|
||||
};
|
||||
let getChromeWindowMock = sinon.stub();
|
||||
getChromeWindowMock.returns(chromeWindowMock);
|
||||
|
||||
sinon.stub(listStore, "getData");
|
||||
|
||||
@ -143,6 +159,7 @@ add_task(function* testPanelStatus() {
|
||||
deckStore,
|
||||
listComponent,
|
||||
SyncedTabs: SyncedTabsMock,
|
||||
getChromeWindowMock
|
||||
});
|
||||
|
||||
let isAuthed = false;
|
||||
@ -152,6 +169,11 @@ add_task(function* testPanelStatus() {
|
||||
|
||||
isAuthed = true;
|
||||
|
||||
loginFailed = true;
|
||||
result = yield component.getPanelStatus();
|
||||
Assert.equal(result, component.PANELS.NOT_AUTHED_INFO);
|
||||
loginFailed = false;
|
||||
|
||||
SyncedTabsMock.isConfiguredToSyncTabs = false;
|
||||
result = yield component.getPanelStatus();
|
||||
Assert.equal(result, component.PANELS.TABS_DISABLED);
|
||||
|
@ -373,7 +373,8 @@ const kTestPairs = [
|
||||
];
|
||||
|
||||
Components.utils.import("resource://gre/modules/Timer.jsm");
|
||||
let detectorModule = Components.utils.import("resource:///modules/translation/LanguageDetector.jsm");
|
||||
let detectorModule = Components.utils.import("resource:///modules/translation/LanguageDetector.jsm", {});
|
||||
const LanguageDetector = detectorModule.LanguageDetector;
|
||||
|
||||
function check_result(result, langCode, expected) {
|
||||
equal(result.language, langCode, "Expected language code");
|
||||
|
@ -32,7 +32,7 @@ var tests = [
|
||||
let windowDestroyedDeferred = Promise.defer();
|
||||
let onDOMWindowDestroyed = (aWindow) => {
|
||||
if (gContentWindow && aWindow == gContentWindow) {
|
||||
Services.obs.removeObserver(onDOMWindowDestroyed, "dom-window-destroyed", false);
|
||||
Services.obs.removeObserver(onDOMWindowDestroyed, "dom-window-destroyed");
|
||||
windowDestroyedDeferred.resolve();
|
||||
}
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ add_task(function* test_setup() {
|
||||
Services.prefs.setCharPref(PREF_MANIFEST_URI, gManifestHandlerURI);
|
||||
Services.prefs.setIntPref(PREF_FETCHINTERVAL, 0);
|
||||
|
||||
let ExperimentsScope = Cu.import("resource:///modules/experiments/Experiments.jsm");
|
||||
let ExperimentsScope = Cu.import("resource:///modules/experiments/Experiments.jsm", {});
|
||||
let Experiments = ExperimentsScope.Experiments;
|
||||
|
||||
gPolicy = new Experiments.Policy();
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/TelemetryLog.jsm");
|
||||
var bsp = Cu.import("resource:///modules/experiments/Experiments.jsm");
|
||||
var {TELEMETRY_LOG, Experiments} = Cu.import("resource:///modules/experiments/Experiments.jsm", {});
|
||||
|
||||
|
||||
const MANIFEST_HANDLER = "manifests/handler";
|
||||
@ -21,7 +21,7 @@ var gPolicy = null;
|
||||
var gManifestObject = null;
|
||||
var gManifestHandlerURI = null;
|
||||
|
||||
const TLOG = bsp.TELEMETRY_LOG;
|
||||
const TLOG = TELEMETRY_LOG;
|
||||
|
||||
function checkEvent(event, id, data) {
|
||||
do_print("Checking message " + id);
|
||||
|
@ -197,11 +197,11 @@ var PdfJs = {
|
||||
|
||||
uninit: function uninit() {
|
||||
if (this._initialized) {
|
||||
Services.prefs.removeObserver(PREF_DISABLED, this, false);
|
||||
Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
|
||||
Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
|
||||
Services.prefs.removeObserver(PREF_DISABLED, this);
|
||||
Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this);
|
||||
Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED);
|
||||
Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED);
|
||||
this._initialized = false;
|
||||
}
|
||||
this._ensureUnregistered();
|
||||
|
@ -110,7 +110,7 @@ var PdfjsChromeUtils = {
|
||||
this._mmg.removeMessageListener('PDFJS:Parent:removeEventListener', this);
|
||||
this._mmg.removeMessageListener('PDFJS:Parent:updateControlState', this);
|
||||
|
||||
Services.obs.removeObserver(this, 'quit-application', false);
|
||||
Services.obs.removeObserver(this, 'quit-application');
|
||||
|
||||
this._mmg = null;
|
||||
this._ppmm = null;
|
||||
|
@ -756,6 +756,10 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
when Sync is configured but syncing tabs is disabled. -->
|
||||
<!ENTITY syncedTabs.sidebar.tabsnotsyncing.label "Turn on tab syncing to view a list of tabs from your other devices.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (syncedTabs.context.open.accesskey,
|
||||
syncedTabs.context.openAllInTabs.accesskey):
|
||||
These access keys are identical because their associated menu items are
|
||||
mutually exclusive -->
|
||||
<!ENTITY syncedTabs.context.open.label "Open">
|
||||
<!ENTITY syncedTabs.context.open.accesskey "O">
|
||||
<!ENTITY syncedTabs.context.openInNewTab.label "Open in a New Tab">
|
||||
@ -769,6 +773,9 @@ you can use these alternative items. Otherwise, their values should be empty. -
|
||||
<!ENTITY syncedTabs.context.copy.label "Copy">
|
||||
<!ENTITY syncedTabs.context.copy.accesskey "C">
|
||||
|
||||
<!ENTITY syncedTabs.context.openAllInTabs.label "Open All in Tabs">
|
||||
<!ENTITY syncedTabs.context.openAllInTabs.accesskey "O">
|
||||
|
||||
|
||||
<!ENTITY syncBrand.shortName.label "Sync">
|
||||
|
||||
|
@ -597,8 +597,6 @@ emeNotifications.drmContentPlaying.message2 = Some audio or video on this site u
|
||||
emeNotifications.drmContentPlaying.button.label = Configure…
|
||||
emeNotifications.drmContentPlaying.button.accesskey = C
|
||||
|
||||
# LOCALIZATION NOTE(emeNotifications.drmContentDisabled.message): NB: inserted via innerHTML, so please don't use <, > or & in this string. %S will be the 'learn more' link
|
||||
emeNotifications.drmContentDisabled.message = You must enable DRM to play some audio or video on this page. %S
|
||||
emeNotifications.drmContentDisabled.button.label = Enable DRM
|
||||
emeNotifications.drmContentDisabled.button.accesskey = E
|
||||
# LOCALIZATION NOTE(emeNotifications.drmContentDisabled.learnMoreLabel): NB: inserted via innerHTML, so please don't use <, > or & in this string.
|
||||
@ -728,10 +726,8 @@ pendingCrashReports.alwaysSend = Always Send
|
||||
decoder.noCodecs.button = Learn how
|
||||
decoder.noCodecs.accesskey = L
|
||||
decoder.noCodecs.message = To play video, you may need to install Microsoft’s Media Feature Pack.
|
||||
decoder.noCodecsVista.message = To play video, you may need to install Microsoft’s Platform Update Supplement for Windows Vista.
|
||||
decoder.noCodecsLinux.message = To play video, you may need to install the required video codecs.
|
||||
decoder.noHWAcceleration.message = To improve video quality, you may need to install Microsoft’s Media Feature Pack.
|
||||
decoder.noHWAccelerationVista.message = To improve video quality, you may need to install Microsoft’s Platform Update Supplement for Windows Vista.
|
||||
decoder.noPulseAudio.message = To play audio, you may need to install the required PulseAudio software.
|
||||
decoder.unsupportedLibavcodec.message = libavcodec may be vulnerable or is not supported, and should be updated to play video.
|
||||
|
||||
|
@ -7,3 +7,5 @@
|
||||
<!ENTITY hostCol.label "Site">
|
||||
<!ENTITY statusCol.label "Status">
|
||||
<!ENTITY usageCol.label "Storage">
|
||||
<!ENTITY search.label "Search:">
|
||||
<!ENTITY search.accesskey "S">
|
||||
|
@ -212,7 +212,7 @@ let urlbarListener = {
|
||||
},
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, AUTOCOMPLETE_ENTER_TEXT_TOPIC, true);
|
||||
Services.obs.removeObserver(this, AUTOCOMPLETE_ENTER_TEXT_TOPIC);
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
@ -300,9 +300,9 @@ let BrowserUsageTelemetry = {
|
||||
},
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, DOMWINDOW_OPENED_TOPIC, false);
|
||||
Services.obs.removeObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC, false);
|
||||
Services.obs.removeObserver(this, WINDOWS_RESTORED_TOPIC, false);
|
||||
Services.obs.removeObserver(this, DOMWINDOW_OPENED_TOPIC);
|
||||
Services.obs.removeObserver(this, TELEMETRY_SUBSESSIONSPLIT_TOPIC);
|
||||
Services.obs.removeObserver(this, WINDOWS_RESTORED_TOPIC);
|
||||
urlbarListener.uninit();
|
||||
},
|
||||
|
||||
|
@ -909,9 +909,9 @@ this.PluginCrashReporter = {
|
||||
},
|
||||
|
||||
uninit() {
|
||||
Services.obs.removeObserver(this, "plugin-crashed", false);
|
||||
Services.obs.removeObserver(this, "gmp-plugin-crash", false);
|
||||
Services.obs.removeObserver(this, "profile-after-change", false);
|
||||
Services.obs.removeObserver(this, "plugin-crashed");
|
||||
Services.obs.removeObserver(this, "gmp-plugin-crash");
|
||||
Services.obs.removeObserver(this, "profile-after-change");
|
||||
this.initialized = false;
|
||||
},
|
||||
|
||||
|
@ -21,6 +21,15 @@ this.ExtensionsUI = {
|
||||
observe(subject, topic, data) {
|
||||
if (topic == "webextension-permission-prompt") {
|
||||
let {target, info} = subject.wrappedJSObject;
|
||||
|
||||
// Dismiss the progress notification. Note that this is bad if
|
||||
// there are multiple simultaneous installs happening, see
|
||||
// bug 1329884 for a longer explanation.
|
||||
let progressNotification = target.ownerGlobal.PopupNotifications.getNotification("addon-progress", target);
|
||||
if (progressNotification) {
|
||||
progressNotification.remove();
|
||||
}
|
||||
|
||||
this.showPermissionsPrompt(target, info).then(answer => {
|
||||
Services.obs.notifyObservers(subject, "webextension-permission-response",
|
||||
JSON.stringify(answer));
|
||||
|
@ -14,6 +14,8 @@ support-files =
|
||||
contentSearchBadImage.xml
|
||||
contentSearchSuggestions.sjs
|
||||
contentSearchSuggestions.xml
|
||||
!/browser/components/search/test/head.js
|
||||
!/browser/components/search/test/testEngine.xml
|
||||
[browser_NetworkPrioritizer.js]
|
||||
[browser_PermissionUI.js]
|
||||
[browser_ProcessHangNotifications.js]
|
||||
|
@ -7,6 +7,24 @@ const CONTENT_SEARCH_MSG = "ContentSearch";
|
||||
const TEST_CONTENT_SCRIPT_BASENAME = "contentSearch.js";
|
||||
|
||||
var gMsgMan;
|
||||
/* eslint no-undef:"error" */
|
||||
/* import-globals-from ../../components/search/test/head.js */
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/browser/components/search/test/head.js",
|
||||
this);
|
||||
|
||||
let originalEngine = Services.search.currentEngine;
|
||||
|
||||
add_task(function* setup() {
|
||||
yield promiseNewEngine("testEngine.xml", {
|
||||
setAsCurrent: true,
|
||||
testPath: "chrome://mochitests/content/browser/browser/components/search/test/",
|
||||
});
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.search.currentEngine = originalEngine;
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* GetState() {
|
||||
yield addTab();
|
||||
|
@ -60,12 +60,12 @@ add_task(function* asyncCleanup() {
|
||||
function promiseObserverNotification(aObserver) {
|
||||
let deferred = Promise.defer();
|
||||
function notificationCallback(e) {
|
||||
Services.obs.removeObserver(notificationCallback, aObserver, false);
|
||||
Services.obs.removeObserver(notificationCallback, aObserver);
|
||||
clearTimeout(timeoutId);
|
||||
deferred.resolve();
|
||||
}
|
||||
let timeoutId = setTimeout(() => {
|
||||
Services.obs.removeObserver(notificationCallback, aObserver, false);
|
||||
Services.obs.removeObserver(notificationCallback, aObserver);
|
||||
deferred.reject("Notification '" + aObserver + "' did not happen within 20 seconds.");
|
||||
}, kTimeoutInMS);
|
||||
Services.obs.addObserver(notificationCallback, aObserver, false);
|
||||
|
@ -18,12 +18,6 @@ content.addEventListener(SERVICE_EVENT_TYPE, event => {
|
||||
|
||||
// Forward messages from the test to the in-content service.
|
||||
addMessageListener(TEST_MSG, msg => {
|
||||
content.dispatchEvent(
|
||||
new content.CustomEvent(CLIENT_EVENT_TYPE, {
|
||||
detail: msg.data,
|
||||
})
|
||||
);
|
||||
|
||||
// If the message is a search, stop the page from loading and then tell the
|
||||
// test that it loaded.
|
||||
if (msg.data.type == "Search") {
|
||||
@ -34,6 +28,12 @@ addMessageListener(TEST_MSG, msg => {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
content.dispatchEvent(
|
||||
new content.CustomEvent(CLIENT_EVENT_TYPE, {
|
||||
detail: msg.data,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
function waitForLoadAndStopIt(expectedURL, callback) {
|
||||
|
@ -117,16 +117,16 @@ body.compact .newtab-cell {
|
||||
}
|
||||
|
||||
/* SITES */
|
||||
body:not(.compact) .newtab-site {
|
||||
.newtab-site {
|
||||
border-radius: var(--cell-corner-radius);
|
||||
box-shadow: 0 1px 3px #c1c1c1;
|
||||
text-decoration: none;
|
||||
transition-property: top, left, opacity, box-shadow, background-color;
|
||||
}
|
||||
|
||||
body:not(.compact) .newtab-cell:not([ignorehover]) .newtab-control:hover ~ .newtab-link,
|
||||
body:not(.compact) .newtab-cell:not([ignorehover]) .newtab-link:hover,
|
||||
body:not(.compact) .newtab-site[dragged] {
|
||||
.newtab-cell:not([ignorehover]) .newtab-control:hover ~ .newtab-link,
|
||||
.newtab-cell:not([ignorehover]) .newtab-link:hover,
|
||||
.newtab-site[dragged] {
|
||||
border: 2px solid white;
|
||||
box-shadow: 0 0 6px 1px #add6ff;
|
||||
margin: -2px;
|
||||
|
@ -29,12 +29,14 @@ AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
|
||||
esac
|
||||
fi
|
||||
|
||||
# if we are debugging, profiling or using sanitizers, we want a frame pointer.
|
||||
# If we are debugging, profiling, using sanitizers, or on win32 we want a
|
||||
# frame pointer.
|
||||
if test -z "$MOZ_OPTIMIZE" -o \
|
||||
-n "$MOZ_PROFILING" -o \
|
||||
-n "$MOZ_DEBUG" -o \
|
||||
-n "$MOZ_MSAN" -o \
|
||||
-n "$MOZ_ASAN"; then
|
||||
-n "$MOZ_ASAN" -o \
|
||||
"$OS_ARCH:$CPU_ARCH" = "WINNT:x86"; then
|
||||
MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
|
||||
else
|
||||
MOZ_FRAMEPTR_FLAGS="$MOZ_DISABLE_FRAME_PTR"
|
||||
|
@ -98,14 +98,17 @@ AC_SUBST(USE_ICU)
|
||||
AC_SUBST(ICU_DATA_FILE)
|
||||
AC_SUBST(MOZ_ICU_DATA_ARCHIVE)
|
||||
|
||||
if test -n "$USE_ICU" -a -z "$MOZ_SYSTEM_ICU"; then
|
||||
if test -z "$YASM" -a -z "$GNU_AS" -a "$COMPILE_ENVIRONMENT"; then
|
||||
AC_MSG_ERROR([Building ICU requires either yasm or a GNU assembler. If you do not have either of those available for this platform you must use --without-intl-api])
|
||||
fi
|
||||
dnl We build ICU as a static library.
|
||||
AC_DEFINE(U_STATIC_IMPLEMENTATION)
|
||||
if test -n "$USE_ICU"; then
|
||||
dnl Source files that use ICU should have control over which parts of the ICU
|
||||
dnl namespace they want to use.
|
||||
AC_DEFINE(U_USING_ICU_NAMESPACE,0)
|
||||
|
||||
if test -z "$MOZ_SYSTEM_ICU"; then
|
||||
if test -z "$YASM" -a -z "$GNU_AS" -a "$COMPILE_ENVIRONMENT"; then
|
||||
AC_MSG_ERROR([Building ICU requires either yasm or a GNU assembler. If you do not have either of those available for this platform you must use --without-intl-api])
|
||||
fi
|
||||
dnl We build ICU as a static library.
|
||||
AC_DEFINE(U_STATIC_IMPLEMENTATION)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
@ -184,6 +184,7 @@ inline bool isIgnoredPathForImplicitCtor(const Decl *Declaration) {
|
||||
End = llvm::sys::path::rend(FileName);
|
||||
for (; Begin != End; ++Begin) {
|
||||
if (Begin->compare_lower(StringRef("skia")) == 0 ||
|
||||
Begin->compare_lower(StringRef("sfntly")) == 0 ||
|
||||
Begin->compare_lower(StringRef("angle")) == 0 ||
|
||||
Begin->compare_lower(StringRef("harfbuzz")) == 0 ||
|
||||
Begin->compare_lower(StringRef("hunspell")) == 0 ||
|
||||
@ -241,6 +242,7 @@ inline bool isIgnoredPathForSprintfLiteral(const CallExpr *Call, const SourceMan
|
||||
Begin->compare_lower(StringRef("mtransport")) == 0 ||
|
||||
Begin->compare_lower(StringRef("protobuf")) == 0 ||
|
||||
Begin->compare_lower(StringRef("skia")) == 0 ||
|
||||
Begin->compare_lower(StringRef("sfntly")) == 0 ||
|
||||
// Gtest uses snprintf as GTEST_SNPRINTF_ with sizeof
|
||||
Begin->compare_lower(StringRef("testing")) == 0) {
|
||||
return true;
|
||||
|
@ -14,4 +14,6 @@ fi
|
||||
MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-1}
|
||||
|
||||
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=c:/builds/crash-stats-api.token
|
||||
export MAKECAB=$topsrcdir/makecab.exe
|
||||
|
||||
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
|
||||
export MAKECAB=$TOOLTOOL_DIR/makecab.exe
|
||||
|
@ -1317,6 +1317,7 @@ xlocale.h
|
||||
#ifdef MOZ_SYSTEM_ICU
|
||||
unicode/locid.h
|
||||
unicode/numsys.h
|
||||
unicode/plurrule.h
|
||||
unicode/timezone.h
|
||||
unicode/ucal.h
|
||||
unicode/uchar.h
|
||||
@ -1327,6 +1328,7 @@ unicode/udatpg.h
|
||||
unicode/uenum.h
|
||||
unicode/unorm.h
|
||||
unicode/unum.h
|
||||
unicode/upluralrules.h
|
||||
unicode/ustring.h
|
||||
unicode/utypes.h
|
||||
#endif
|
||||
|
@ -283,6 +283,8 @@ module.exports = {
|
||||
"no-return-assign": "error",
|
||||
// Allow use of javascript: urls.
|
||||
"no-script-url": "off",
|
||||
// Disallow assignments like foo = foo
|
||||
"no-self-assign": "error",
|
||||
// Disallow comparisons where both sides are exactly the same.
|
||||
"no-self-compare": "error",
|
||||
// Disallow use of comma operator.
|
||||
@ -332,6 +334,10 @@ module.exports = {
|
||||
"no-unsafe-finally": "error",
|
||||
// Allow using variables before they are defined.
|
||||
"no-use-before-define": "off",
|
||||
// Disallow useless Function.prototype.{call/apply}
|
||||
"no-useless-call": "error",
|
||||
// Disallow useless return;
|
||||
"no-useless-return": "error",
|
||||
// We use var-only-at-top-level instead of no-var as we allow top level
|
||||
// vars.
|
||||
"no-var": "off",
|
||||
|
@ -122,7 +122,7 @@ add_task(function* reloadButtonReloadsAddon() {
|
||||
|
||||
const onBootstrapInstallCalled = new Promise(done => {
|
||||
Services.obs.addObserver(function listener() {
|
||||
Services.obs.removeObserver(listener, ADDON_NAME, false);
|
||||
Services.obs.removeObserver(listener, ADDON_NAME);
|
||||
info("Add-on was re-installed: " + ADDON_NAME);
|
||||
done();
|
||||
}, ADDON_NAME, false);
|
||||
|
@ -543,7 +543,5 @@ SelectorAutocompleter.prototype = {
|
||||
// the autoSelect item has been selected.
|
||||
return this._showPopup(result.suggestions, firstPart, state);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -1089,11 +1089,11 @@ CssRuleView.prototype = {
|
||||
this.element.appendChild(div);
|
||||
}
|
||||
|
||||
let inheritedSource = rule.inheritedSource;
|
||||
let inheritedSource = rule.inherited;
|
||||
if (inheritedSource && inheritedSource !== lastInheritedSource) {
|
||||
let div = this.styleDocument.createElementNS(HTML_NS, "div");
|
||||
div.className = this._getRuleViewHeaderClassName();
|
||||
div.textContent = inheritedSource;
|
||||
div.textContent = rule.inheritedSource;
|
||||
lastInheritedSource = inheritedSource;
|
||||
this.element.appendChild(div);
|
||||
}
|
||||
@ -1607,7 +1607,6 @@ RuleViewTool.prototype = {
|
||||
toolbox.getCurrentPanel().selectStyleSheet(url, line, column);
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -150,6 +150,7 @@ skip-if = (os == "win" && debug) # bug 963492: win.
|
||||
[browser_rules_inherited-properties_01.js]
|
||||
[browser_rules_inherited-properties_02.js]
|
||||
[browser_rules_inherited-properties_03.js]
|
||||
[browser_rules_inherited-properties_04.js]
|
||||
[browser_rules_inline-source-map.js]
|
||||
[browser_rules_invalid.js]
|
||||
[browser_rules_invalid-source-map.js]
|
||||
|
@ -0,0 +1,32 @@
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that different inherited properties sections are created for rules
|
||||
// inherited from several elements of the same type.
|
||||
|
||||
const TEST_URI = `
|
||||
<div style="cursor:pointer">
|
||||
A
|
||||
<div style="cursor:pointer">
|
||||
B<a>Cursor</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("a", inspector);
|
||||
yield elementStyleInherit(inspector, view);
|
||||
});
|
||||
|
||||
function* elementStyleInherit(inspector, view) {
|
||||
let gutters = view.element.querySelectorAll(".theme-gutter");
|
||||
is(gutters.length, 2,
|
||||
"Gutters should contains 2 sections");
|
||||
ok(gutters[0].textContent, "Inherited from div");
|
||||
ok(gutters[1].textContent, "Inherited from div");
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
.getService(SpecialPowers.Ci.nsIIOService);
|
||||
|
||||
var style = "data:text/css,a { background-color: seagreen; }";
|
||||
var uri = gIOService.newURI(style, null, null);
|
||||
var uri = gIOService.newURI(style);
|
||||
var windowUtils = SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
|
||||
|
@ -14,7 +14,7 @@
|
||||
.getService(SpecialPowers.Ci.nsIIOService);
|
||||
|
||||
var style = "data:text/css,div { background-color: seagreen; }";
|
||||
var uri = gIOService.newURI(style, null, null);
|
||||
var uri = gIOService.newURI(style);
|
||||
var windowUtils = SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIDOMWindowUtils);
|
||||
|
@ -119,6 +119,10 @@ requestCookies=Request cookies
|
||||
# in the network details params tab identifying the response cookies.
|
||||
responseCookies=Response cookies
|
||||
|
||||
# LOCALIZATION NOTE (responsePayload): This is the label displayed
|
||||
# in the network details response tab identifying the response payload.
|
||||
responsePayload=Response payload
|
||||
|
||||
# LOCALIZATION NOTE (jsonFilterText): This is the text displayed
|
||||
# in the response tab of the network details pane for the JSON filtering input.
|
||||
jsonFilterText=Filter properties
|
||||
|
@ -644,7 +644,6 @@ exports.fetchImmediatelyDominated = TaskCache.declareCacheableTask({
|
||||
nodes: response.nodes,
|
||||
moreChildrenAvailable: response.moreChildrenAvailable,
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
@ -700,17 +699,15 @@ exports.refreshSelectedDominatorTree = function (heapWorker) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to check for the snapshot state because if there was an error,
|
||||
// we can't continue and if we are still saving or reading the snapshot,
|
||||
// then takeSnapshotAndCensus will finish the job for us
|
||||
if (snapshot.state === states.READ) {
|
||||
if (snapshot.dominatorTree) {
|
||||
yield dispatch(fetchDominatorTree(heapWorker, snapshot.id));
|
||||
} else {
|
||||
yield dispatch(computeAndFetchDominatorTree(heapWorker, snapshot.id));
|
||||
}
|
||||
} else {
|
||||
// If there was an error, we can't continue. If we are still saving or
|
||||
// reading the snapshot, then takeSnapshotAndCensus will finish the job
|
||||
// for us.
|
||||
return;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -8,6 +8,8 @@ const general = {
|
||||
CONTENT_SIZE_DECIMALS: 2,
|
||||
FILTER_SEARCH_DELAY: 200,
|
||||
REQUEST_TIME_DECIMALS: 2,
|
||||
// 100 KB in bytes
|
||||
SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE: 102400,
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
|
@ -3,51 +3,32 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
/* globals window, dumpn, $, NetMonitorView, gNetwork */
|
||||
/* globals window, dumpn, $, gNetwork */
|
||||
|
||||
"use strict";
|
||||
|
||||
const promise = require("promise");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Editor = require("devtools/client/sourceeditor/editor");
|
||||
const { Heritage } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { ToolSidebar } = require("devtools/client/framework/sidebar");
|
||||
const { VariablesView } = require("resource://devtools/client/shared/widgets/VariablesView.jsm");
|
||||
const { VariablesViewController } = require("resource://devtools/client/shared/widgets/VariablesViewController.jsm");
|
||||
const { EVENTS } = require("./events");
|
||||
const { L10N } = require("./l10n");
|
||||
const { Filters } = require("./filter-predicates");
|
||||
const {
|
||||
decodeUnicodeUrl,
|
||||
formDataURI,
|
||||
getUrlBaseName,
|
||||
} = require("./request-utils");
|
||||
const { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
const ParamsPanel = createFactory(require("./shared/components/params-panel"));
|
||||
const PreviewPanel = createFactory(require("./shared/components/preview-panel"));
|
||||
const ResponsePanel = createFactory(require("./shared/components/response-panel"));
|
||||
const SecurityPanel = createFactory(require("./shared/components/security-panel"));
|
||||
const TimingsPanel = createFactory(require("./shared/components/timings-panel"));
|
||||
|
||||
// 100 KB in bytes
|
||||
const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 102400;
|
||||
const HEADERS_SIZE_DECIMALS = 3;
|
||||
const CONTENT_MIME_TYPE_MAPPINGS = {
|
||||
"/ecmascript": Editor.modes.js,
|
||||
"/javascript": Editor.modes.js,
|
||||
"/x-javascript": Editor.modes.js,
|
||||
"/html": Editor.modes.html,
|
||||
"/xhtml": Editor.modes.html,
|
||||
"/xml": Editor.modes.html,
|
||||
"/atom": Editor.modes.html,
|
||||
"/soap": Editor.modes.html,
|
||||
"/vnd.mpeg.dash.mpd": Editor.modes.html,
|
||||
"/rdf": Editor.modes.css,
|
||||
"/rss": Editor.modes.css,
|
||||
"/css": Editor.modes.css
|
||||
};
|
||||
const GENERIC_VARIABLES_VIEW_SETTINGS = {
|
||||
lazyEmpty: true,
|
||||
// ms
|
||||
@ -106,6 +87,13 @@ DetailsView.prototype = {
|
||||
PreviewPanel()
|
||||
), this._previewPanelNode);
|
||||
|
||||
this._responsePanelNode = $("#react-response-tabpanel-hook");
|
||||
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
ResponsePanel()
|
||||
), this._responsePanelNode);
|
||||
|
||||
this._securityPanelNode = $("#react-security-tabpanel-hook");
|
||||
|
||||
ReactDOM.render(Provider(
|
||||
@ -136,12 +124,6 @@ DetailsView.prototype = {
|
||||
emptyText: L10N.getStr("cookiesEmptyText"),
|
||||
searchPlaceholder: L10N.getStr("cookiesFilterText")
|
||||
}));
|
||||
this._json = new VariablesView($("#response-content-json"),
|
||||
Heritage.extend(GENERIC_VARIABLES_VIEW_SETTINGS, {
|
||||
onlyEnumVisible: true,
|
||||
searchPlaceholder: L10N.getStr("jsonFilterText")
|
||||
}));
|
||||
VariablesViewController.attach(this._json);
|
||||
|
||||
this._requestHeaders = L10N.getStr("requestHeaders");
|
||||
this._requestHeadersFromUpload = L10N.getStr("requestHeadersFromUpload");
|
||||
@ -159,6 +141,7 @@ DetailsView.prototype = {
|
||||
dumpn("Destroying the DetailsView");
|
||||
ReactDOM.unmountComponentAtNode(this._paramsPanelNode);
|
||||
ReactDOM.unmountComponentAtNode(this._previewPanelNode);
|
||||
ReactDOM.unmountComponentAtNode(this._responsePanelNode);
|
||||
ReactDOM.unmountComponentAtNode(this._securityPanelNode);
|
||||
ReactDOM.unmountComponentAtNode(this._timingsPanelNode);
|
||||
this.sidebar.destroy();
|
||||
@ -175,11 +158,7 @@ DetailsView.prototype = {
|
||||
* Returns a promise that resolves upon population the view.
|
||||
*/
|
||||
populate: function (data) {
|
||||
$("#response-content-info-header").hidden = true;
|
||||
$("#response-content-json-box").hidden = true;
|
||||
$("#response-content-textarea-box").hidden = true;
|
||||
$("#raw-headers").hidden = true;
|
||||
$("#response-content-image-box").hidden = true;
|
||||
|
||||
let isHtml = Filters.html(data);
|
||||
|
||||
@ -205,7 +184,6 @@ DetailsView.prototype = {
|
||||
|
||||
this._headers.empty();
|
||||
this._cookies.empty();
|
||||
this._json.empty();
|
||||
|
||||
this._dataSrc = { src: data, populated: [] };
|
||||
this._onTabSelect();
|
||||
@ -254,10 +232,6 @@ DetailsView.prototype = {
|
||||
yield view._setResponseCookies(src.responseCookies);
|
||||
yield view._setRequestCookies(src.requestCookies);
|
||||
break;
|
||||
// "Response"
|
||||
case 3:
|
||||
yield view._setResponseBody(src.url, src.responseContent);
|
||||
break;
|
||||
}
|
||||
viewState.updating[tab] = false;
|
||||
}).then(() => {
|
||||
@ -471,125 +445,9 @@ DetailsView.prototype = {
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets the network response body shown in this view.
|
||||
*
|
||||
* @param string url
|
||||
* The request's url.
|
||||
* @param object response
|
||||
* The message received from the server.
|
||||
* @return object
|
||||
* A promise that is resolved when the response body is set.
|
||||
*/
|
||||
_setResponseBody: Task.async(function* (url, response) {
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
let { mimeType, text, encoding } = response.content;
|
||||
let responseBody = yield gNetwork.getString(text);
|
||||
|
||||
// Handle json, which we tentatively identify by checking the MIME type
|
||||
// for "json" after any word boundary. This works for the standard
|
||||
// "application/json", and also for custom types like "x-bigcorp-json".
|
||||
// Additionally, we also directly parse the response text content to
|
||||
// verify whether it's json or not, to handle responses incorrectly
|
||||
// labeled as text/plain instead.
|
||||
let jsonMimeType, jsonObject, jsonObjectParseError;
|
||||
try {
|
||||
jsonMimeType = /\bjson/.test(mimeType);
|
||||
jsonObject = JSON.parse(responseBody);
|
||||
} catch (e) {
|
||||
jsonObjectParseError = e;
|
||||
}
|
||||
if (jsonMimeType || jsonObject) {
|
||||
// Extract the actual json substring in case this might be a "JSONP".
|
||||
// This regex basically parses a function call and captures the
|
||||
// function name and arguments in two separate groups.
|
||||
let jsonpRegex = /^\s*([\w$]+)\s*\(\s*([^]*)\s*\)\s*;?\s*$/;
|
||||
let [_, callbackPadding, jsonpString] = // eslint-disable-line
|
||||
responseBody.match(jsonpRegex) || [];
|
||||
|
||||
// Make sure this is a valid JSON object first. If so, nicely display
|
||||
// the parsing results in a variables view. Otherwise, simply show
|
||||
// the contents as plain text.
|
||||
if (callbackPadding && jsonpString) {
|
||||
try {
|
||||
jsonObject = JSON.parse(jsonpString);
|
||||
} catch (e) {
|
||||
jsonObjectParseError = e;
|
||||
}
|
||||
}
|
||||
|
||||
// Valid JSON or JSONP.
|
||||
if (jsonObject) {
|
||||
$("#response-content-json-box").hidden = false;
|
||||
let jsonScopeName = callbackPadding
|
||||
? L10N.getFormatStr("jsonpScopeName", callbackPadding)
|
||||
: L10N.getStr("jsonScopeName");
|
||||
|
||||
let jsonVar = { label: jsonScopeName, rawObject: jsonObject };
|
||||
yield this._json.controller.setSingleVariable(jsonVar).expanded;
|
||||
} else {
|
||||
// Malformed JSON.
|
||||
$("#response-content-textarea-box").hidden = false;
|
||||
let infoHeader = $("#response-content-info-header");
|
||||
infoHeader.setAttribute("value", jsonObjectParseError);
|
||||
infoHeader.setAttribute("tooltiptext", jsonObjectParseError);
|
||||
infoHeader.hidden = false;
|
||||
|
||||
let editor = yield NetMonitorView.editor("#response-content-textarea");
|
||||
editor.setMode(Editor.modes.js);
|
||||
editor.setText(responseBody);
|
||||
}
|
||||
} else if (mimeType.includes("image/")) {
|
||||
// Handle images.
|
||||
$("#response-content-image-box").setAttribute("align", "center");
|
||||
$("#response-content-image-box").setAttribute("pack", "center");
|
||||
$("#response-content-image-box").hidden = false;
|
||||
$("#response-content-image").src = formDataURI(mimeType, encoding, responseBody);
|
||||
|
||||
// Immediately display additional information about the image:
|
||||
// file name, mime type and encoding.
|
||||
$("#response-content-image-name-value").setAttribute("value",
|
||||
getUrlBaseName(url));
|
||||
$("#response-content-image-mime-value").setAttribute("value", mimeType);
|
||||
|
||||
// Wait for the image to load in order to display the width and height.
|
||||
$("#response-content-image").onload = e => {
|
||||
// XUL images are majestic so they don't bother storing their dimensions
|
||||
// in width and height attributes like the rest of the folk. Hack around
|
||||
// this by getting the bounding client rect and subtracting the margins.
|
||||
let { width, height } = e.target.getBoundingClientRect();
|
||||
let dimensions = (width - 2) + " \u00D7 " + (height - 2);
|
||||
$("#response-content-image-dimensions-value").setAttribute("value",
|
||||
dimensions);
|
||||
};
|
||||
} else {
|
||||
$("#response-content-textarea-box").hidden = false;
|
||||
let editor = yield NetMonitorView.editor("#response-content-textarea");
|
||||
editor.setMode(Editor.modes.text);
|
||||
editor.setText(responseBody);
|
||||
|
||||
// Maybe set a more appropriate mode in the Source Editor if possible,
|
||||
// but avoid doing this for very large files.
|
||||
if (responseBody.length < SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
|
||||
let mapping = Object.keys(CONTENT_MIME_TYPE_MAPPINGS).find(key => {
|
||||
return mimeType.includes(key);
|
||||
});
|
||||
|
||||
if (mapping) {
|
||||
editor.setMode(CONTENT_MIME_TYPE_MAPPINGS[mapping]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.emit(EVENTS.RESPONSE_BODY_DISPLAYED);
|
||||
}),
|
||||
|
||||
_dataSrc: null,
|
||||
_headers: null,
|
||||
_cookies: null,
|
||||
_json: null,
|
||||
_requestHeaders: "",
|
||||
_responseHeaders: "",
|
||||
_requestCookies: "",
|
||||
|
@ -55,9 +55,6 @@ const EVENTS = {
|
||||
// When the request post params are displayed in the UI.
|
||||
REQUEST_POST_PARAMS_DISPLAYED: "NetMonitor:RequestPostParamsAvailable",
|
||||
|
||||
// When the response body is displayed in the UI.
|
||||
RESPONSE_BODY_DISPLAYED: "NetMonitor:ResponseBodyAvailable",
|
||||
|
||||
// When the image response thumbnail is displayed in the UI.
|
||||
RESPONSE_IMAGE_THUMBNAIL_DISPLAYED:
|
||||
"NetMonitor:ResponseImageThumbnailAvailable",
|
||||
|
@ -8,8 +8,6 @@
|
||||
"use strict";
|
||||
|
||||
const { testing: isTesting } = require("devtools/shared/flags");
|
||||
const promise = require("promise");
|
||||
const Editor = require("devtools/client/sourceeditor/editor");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
||||
const { RequestsMenuView } = require("./requests-menu-view");
|
||||
@ -32,12 +30,6 @@ const WDA_DEFAULT_VERIFY_INTERVAL = 50;
|
||||
// ms
|
||||
const WDA_DEFAULT_GIVE_UP_TIMEOUT = isTesting ? 45000 : 2000;
|
||||
|
||||
const DEFAULT_EDITOR_CONFIG = {
|
||||
mode: Editor.modes.text,
|
||||
readOnly: true,
|
||||
lineNumbers: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Object defining the network monitor view components.
|
||||
*/
|
||||
@ -102,11 +94,6 @@ var NetMonitorView = {
|
||||
Prefs.networkDetailsHeight = this._detailsPane.getAttribute("height");
|
||||
|
||||
this._detailsPane = null;
|
||||
|
||||
for (let p of this._editorPromises.values()) {
|
||||
let editor = yield p;
|
||||
editor.destroy();
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
@ -214,35 +201,8 @@ var NetMonitorView = {
|
||||
ACTIVITY_TYPE.RELOAD.WITH_CACHE_DEFAULT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Lazily initializes and returns a promise for a Editor instance.
|
||||
*
|
||||
* @param string id
|
||||
* The id of the editor placeholder node.
|
||||
* @return object
|
||||
* A promise that is resolved when the editor is available.
|
||||
*/
|
||||
editor: function (id) {
|
||||
dumpn("Getting a NetMonitorView editor: " + id);
|
||||
|
||||
if (this._editorPromises.has(id)) {
|
||||
return this._editorPromises.get(id);
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
this._editorPromises.set(id, deferred.promise);
|
||||
|
||||
// Initialize the source editor and store the newly created instance
|
||||
// in the ether of a resolved promise's value.
|
||||
let editor = new Editor(DEFAULT_EDITOR_CONFIG);
|
||||
editor.appendTo($(id)).then(() => deferred.resolve(editor));
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_body: null,
|
||||
_detailsPane: null,
|
||||
_editorPromises: new Map()
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -217,42 +217,8 @@
|
||||
</tabpanel>
|
||||
<tabpanel id="response-tabpanel"
|
||||
class="tabpanel-content">
|
||||
<vbox flex="1">
|
||||
<label id="response-content-info-header"/>
|
||||
<vbox id="response-content-json-box" flex="1" hidden="true">
|
||||
<vbox id="response-content-json" flex="1" context="network-response-popup" />
|
||||
</vbox>
|
||||
<vbox id="response-content-textarea-box" flex="1" hidden="true">
|
||||
<vbox id="response-content-textarea" flex="1"/>
|
||||
</vbox>
|
||||
<vbox id="response-content-image-box" flex="1" hidden="true">
|
||||
<image id="response-content-image"/>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
data-localization="content=netmonitor.response.name"/>
|
||||
<label id="response-content-image-name-value"
|
||||
class="plain tabpanel-summary-value devtools-monospace"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
data-localization="content=netmonitor.response.dimensions"/>
|
||||
<label id="response-content-image-dimensions-value"
|
||||
class="plain tabpanel-summary-value devtools-monospace"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
<hbox>
|
||||
<label class="plain tabpanel-summary-label"
|
||||
data-localization="content=netmonitor.response.mime"/>
|
||||
<label id="response-content-image-mime-value"
|
||||
class="plain tabpanel-summary-value devtools-monospace"
|
||||
crop="end"
|
||||
flex="1"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-response-tabpanel-hook"/>
|
||||
</tabpanel>
|
||||
<tabpanel id="timings-tabpanel"
|
||||
class="tabpanel-content">
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user