зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
92b2943e68
|
@ -84,7 +84,6 @@ browser/extensions/loop/**
|
|||
|
||||
# devtools/ exclusions
|
||||
devtools/*.js
|
||||
devtools/client/*.js
|
||||
devtools/client/aboutdebugging/**
|
||||
devtools/client/animationinspector/**
|
||||
devtools/client/canvasdebugger/**
|
||||
|
|
|
@ -302,7 +302,7 @@ const load = iced(function load(loader, module) {
|
|||
|
||||
let sandbox;
|
||||
if (loader.sharedGlobalSandbox &&
|
||||
loader.sharedGlobalBlacklist.indexOf(module.id) == -1) {
|
||||
loader.sharedGlobalBlocklist.indexOf(module.id) == -1) {
|
||||
// Create a new object in this sandbox, that will be used as
|
||||
// the scope object for this particular module
|
||||
sandbox = new loader.sharedGlobalSandbox.Object();
|
||||
|
@ -810,9 +810,12 @@ Loader.unload = unload;
|
|||
// If `resolve` does not returns `uri` string exception will be thrown by
|
||||
// an associated `require` call.
|
||||
function Loader(options) {
|
||||
if (options.sharedGlobalBlacklist && !options.sharedGlobalBlocklist) {
|
||||
options.sharedGlobalBlocklist = options.sharedGlobalBlacklist;
|
||||
}
|
||||
let {
|
||||
modules, globals, resolve, paths, rootURI, manifest, requireMap, isNative,
|
||||
metadata, sharedGlobal, sharedGlobalBlacklist, checkCompatibility, waiveIntereposition
|
||||
metadata, sharedGlobal, sharedGlobalBlocklist, checkCompatibility, waiveIntereposition
|
||||
} = override({
|
||||
paths: {},
|
||||
modules: {},
|
||||
|
@ -832,7 +835,7 @@ function Loader(options) {
|
|||
// Make the returned resolve function have the same signature
|
||||
(id, requirer) => Loader.nodeResolve(id, requirer, { rootURI: rootURI }) :
|
||||
Loader.resolve,
|
||||
sharedGlobalBlacklist: ["sdk/indexed-db"],
|
||||
sharedGlobalBlocklist: ["sdk/indexed-db"],
|
||||
waiveIntereposition: false
|
||||
}, options);
|
||||
|
||||
|
@ -923,7 +926,8 @@ function Loader(options) {
|
|||
modules: { enumerable: false, value: modules },
|
||||
metadata: { enumerable: false, value: metadata },
|
||||
sharedGlobalSandbox: { enumerable: false, value: sharedGlobalSandbox },
|
||||
sharedGlobalBlacklist: { enumerable: false, value: sharedGlobalBlacklist },
|
||||
sharedGlobalBlocklist: { enumerable: false, value: sharedGlobalBlocklist },
|
||||
sharedGlobalBlacklist: { enumerable: false, value: sharedGlobalBlocklist },
|
||||
// Map of module sandboxes indexed by module URIs.
|
||||
sandboxes: { enumerable: false, value: {} },
|
||||
resolve: { enumerable: false, value: resolve },
|
||||
|
|
|
@ -349,12 +349,41 @@ exports['test console global by default'] = function (assert) {
|
|||
};
|
||||
|
||||
exports['test shared globals'] = function(assert) {
|
||||
let uri = root + '/fixtures/loader/cycles/';
|
||||
let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
|
||||
sharedGlobalBlocklist: ['b'] });
|
||||
|
||||
let program = main(loader, 'main');
|
||||
|
||||
// As it is hard to verify what is the global of an object
|
||||
// (due to wrappers) we check that we see the `foo` symbol
|
||||
// being manually injected into the shared global object
|
||||
loader.sharedGlobalSandbox.foo = true;
|
||||
|
||||
let m = loader.sandboxes[uri + 'main.js'];
|
||||
let a = loader.sandboxes[uri + 'a.js'];
|
||||
let b = loader.sandboxes[uri + 'b.js'];
|
||||
|
||||
assert.ok(Cu.getGlobalForObject(m).foo, "main is shared");
|
||||
assert.ok(Cu.getGlobalForObject(a).foo, "a is shared");
|
||||
assert.ok(!Cu.getGlobalForObject(b).foo, "b isn't shared");
|
||||
|
||||
unload(loader);
|
||||
}
|
||||
|
||||
exports['test deprecated shared globals exception name'] = function(assert) {
|
||||
let uri = root + '/fixtures/loader/cycles/';
|
||||
let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
|
||||
sharedGlobalBlacklist: ['b'] });
|
||||
|
||||
let program = main(loader, 'main');
|
||||
|
||||
assert.ok(loader.sharedGlobalBlocklist.includes("b"), "b should be in the blocklist");
|
||||
assert.equal(loader.sharedGlobalBlocklist.length, loader.sharedGlobalBlacklist.length,
|
||||
"both blocklists should have the same number of items.");
|
||||
assert.equal(loader.sharedGlobalBlocklist.join(","), loader.sharedGlobalBlacklist.join(","),
|
||||
"both blocklists should have the same items.");
|
||||
|
||||
// As it is hard to verify what is the global of an object
|
||||
// (due to wrappers) we check that we see the `foo` symbol
|
||||
// being manually injected into the shared global object
|
||||
|
|
|
@ -1589,6 +1589,9 @@ pref("browser.defaultbrowser.notificationbar", false);
|
|||
// the hang monitor.
|
||||
pref("dom.ipc.cpow.timeout", 500);
|
||||
|
||||
// Causes access on unsafe CPOWs from browser code to throw by default.
|
||||
pref("dom.ipc.cpows.forbid-unsafe-from-browser", true);
|
||||
|
||||
// Enable e10s hang monitoring (slow script checking and plugin hang
|
||||
// detection).
|
||||
pref("dom.ipc.processHangMonitor", true);
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
onclick="checkForMiddleClick(this, event);"
|
||||
label="&helpKeyboardShortcuts.label;"
|
||||
accesskey="&helpKeyboardShortcuts.accesskey;"/>
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<menuitem id="healthReport"
|
||||
label="&healthReport2.label;"
|
||||
accesskey="&healthReport2.accesskey;"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<xul:hbox class="chat-titlebar" xbl:inherits="minimized,selected,activity" align="baseline">
|
||||
<xul:hbox flex="1" onclick="document.getBindingParent(this).onTitlebarClick(event);">
|
||||
<xul:image class="chat-status-icon" xbl:inherits="src=image"/>
|
||||
<xul:label class="chat-title" flex="1" xbl:inherits="value=label" crop="center"/>
|
||||
<xul:label class="chat-title" flex="1" xbl:inherits="crop=titlecrop,value=label" crop="end"/>
|
||||
</xul:hbox>
|
||||
<xul:toolbarbutton anonid="webRTC-shareScreen-icon"
|
||||
class="notification-anchor-icon chat-toolbarbutton"
|
||||
|
|
|
@ -157,7 +157,9 @@ skip-if = buildapp == 'mulet' || toolkit == "windows" # Disabled on Windows due
|
|||
[browser_bug321000.js]
|
||||
skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
|
||||
[browser_bug329212.js]
|
||||
skip-if = e10s # Bug 1236991 - Update or remove tests that use fillInPageTooltip
|
||||
[browser_bug331772_xul_tooltiptext_in_html.js]
|
||||
skip-if = e10s # Bug 1236991 - Update or remove tests that use fillInPageTooltip
|
||||
[browser_bug356571.js]
|
||||
[browser_bug380960.js]
|
||||
[browser_bug386835.js]
|
||||
|
@ -210,6 +212,7 @@ skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notific
|
|||
[browser_bug556061.js]
|
||||
[browser_bug559991.js]
|
||||
[browser_bug561623.js]
|
||||
skip-if = e10s # Bug 1236991 - Update or remove tests that use fillInPageTooltip
|
||||
[browser_bug561636.js]
|
||||
[browser_bug562649.js]
|
||||
[browser_bug563588.js]
|
||||
|
@ -227,6 +230,7 @@ skip-if = toolkit != "cocoa"
|
|||
[browser_bug581242.js]
|
||||
[browser_bug581253.js]
|
||||
[browser_bug581947.js]
|
||||
skip-if = e10s # Bug 1236991 - Update or remove tests that use fillInPageTooltip
|
||||
[browser_bug585558.js]
|
||||
[browser_bug585785.js]
|
||||
[browser_bug585830.js]
|
||||
|
|
|
@ -1,26 +1,34 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
const PAGE = "data:text/html;charset=utf-8,<a href='%23xxx'><span>word1 <span> word2 </span></span><span> word3</span></a>";
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(performTest, content);
|
||||
}, true);
|
||||
/**
|
||||
* Tests that we correctly compute the text for context menu
|
||||
* selection of some content.
|
||||
*/
|
||||
add_task(function*() {
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: PAGE,
|
||||
}, function*(browser) {
|
||||
let contextMenu = document.getElementById("contentAreaContextMenu");
|
||||
let awaitPopupShown = BrowserTestUtils.waitForEvent(contextMenu,
|
||||
"popupshown");
|
||||
let awaitPopupHidden = BrowserTestUtils.waitForEvent(contextMenu,
|
||||
"popuphidden");
|
||||
|
||||
content.location = "data:text/html;charset=utf-8,<a href='%23xxx'><span>word1 <span> word2 </span></span><span> word3</span></a>";
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("a", {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
}, browser);
|
||||
|
||||
function performTest()
|
||||
{
|
||||
let doc = content.document;
|
||||
let link = doc.querySelector("a");;
|
||||
let text = gatherTextUnder(link);
|
||||
is(text, "word1 word2 word3", "Text under link is correctly computed.");
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
yield awaitPopupShown;
|
||||
|
||||
is(gContextMenu.linkTextStr, "word1 word2 word3",
|
||||
"Text under link is correctly computed.");
|
||||
|
||||
contextMenu.hidePopup();
|
||||
yield awaitPopupHidden;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,23 +2,13 @@
|
|||
* 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/. */
|
||||
|
||||
const kObservedTopics = [
|
||||
"getUserMedia:response:allow",
|
||||
"getUserMedia:revoke",
|
||||
"getUserMedia:response:deny",
|
||||
"getUserMedia:request",
|
||||
"recording-device-events",
|
||||
"recording-window-ended"
|
||||
];
|
||||
|
||||
const PREF_PERMISSION_FAKE = "media.navigator.permission.fake";
|
||||
const PREF_LOOP_CSP = "loop.CSP";
|
||||
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
|
||||
"@mozilla.org/mediaManagerService;1",
|
||||
"nsIMediaManagerService");
|
||||
const CONTENT_SCRIPT_HELPER = getRootDirectory(gTestPath) + "get_user_media_content_script.js";
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript(getRootDirectory(gTestPath) + "get_user_media_helpers.js",
|
||||
this);
|
||||
|
||||
var gTab;
|
||||
|
||||
|
@ -53,135 +43,6 @@ function isLinux() {
|
|||
return navigator.platform.indexOf("Linux") != -1;
|
||||
}
|
||||
|
||||
var gObservedTopics = {};
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
if (!(aTopic in gObservedTopics))
|
||||
gObservedTopics[aTopic] = 1;
|
||||
else
|
||||
++gObservedTopics[aTopic];
|
||||
}
|
||||
|
||||
function promiseObserverCalled(aTopic, aAction) {
|
||||
let deferred = Promise.defer();
|
||||
info("Waiting for " + aTopic);
|
||||
|
||||
Services.obs.addObserver(function observer(aSubject, topic, aData) {
|
||||
ok(true, "got " + aTopic + " notification");
|
||||
info("Message: " + aData);
|
||||
Services.obs.removeObserver(observer, aTopic);
|
||||
|
||||
if (kObservedTopics.indexOf(aTopic) != -1) {
|
||||
if (!(aTopic in gObservedTopics))
|
||||
gObservedTopics[aTopic] = -1;
|
||||
else
|
||||
--gObservedTopics[aTopic];
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
}, aTopic, false);
|
||||
|
||||
if (aAction)
|
||||
aAction();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promisePopupNotification(aName) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
waitForCondition(() => PopupNotifications.getNotification(aName),
|
||||
() => {
|
||||
ok(!!PopupNotifications.getNotification(aName),
|
||||
aName + " notification appeared");
|
||||
|
||||
deferred.resolve();
|
||||
}, "timeout waiting for popup notification " + aName);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseNoPopupNotification(aName) {
|
||||
let deferred = Promise.defer();
|
||||
info("Waiting for " + aName + " to be removed");
|
||||
|
||||
waitForCondition(() => !PopupNotifications.getNotification(aName),
|
||||
() => {
|
||||
ok(!PopupNotifications.getNotification(aName),
|
||||
aName + " notification removed");
|
||||
deferred.resolve();
|
||||
}, "timeout waiting for popup notification " + aName + " to disappear");
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function expectObserverCalled(aTopic) {
|
||||
is(gObservedTopics[aTopic], 1, "expected notification " + aTopic);
|
||||
if (aTopic in gObservedTopics)
|
||||
--gObservedTopics[aTopic];
|
||||
}
|
||||
|
||||
function expectNoObserverCalled() {
|
||||
for (let topic in gObservedTopics) {
|
||||
if (gObservedTopics[topic])
|
||||
is(gObservedTopics[topic], 0, topic + " notification unexpected");
|
||||
}
|
||||
gObservedTopics = {};
|
||||
}
|
||||
|
||||
function promiseMessage(aMessage, aAction) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
content.addEventListener("message", function messageListener(event) {
|
||||
content.removeEventListener("message", messageListener);
|
||||
is(event.data, aMessage, "received " + aMessage);
|
||||
if (event.data == aMessage)
|
||||
deferred.resolve();
|
||||
else
|
||||
deferred.reject();
|
||||
});
|
||||
|
||||
if (aAction)
|
||||
aAction();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function getMediaCaptureState() {
|
||||
let hasVideo = {};
|
||||
let hasAudio = {};
|
||||
let hasScreenShare = {};
|
||||
let hasWindowShare = {};
|
||||
MediaManagerService.mediaCaptureWindowState(content, hasVideo, hasAudio,
|
||||
hasScreenShare, hasWindowShare);
|
||||
if (hasVideo.value && hasAudio.value)
|
||||
return "CameraAndMicrophone";
|
||||
if (hasVideo.value)
|
||||
return "Camera";
|
||||
if (hasAudio.value)
|
||||
return "Microphone";
|
||||
if (hasScreenShare)
|
||||
return "Screen";
|
||||
if (hasWindowShare)
|
||||
return "Window";
|
||||
return "none";
|
||||
}
|
||||
|
||||
function* closeStream(aAlreadyClosed) {
|
||||
expectNoObserverCalled();
|
||||
|
||||
info("closing the stream");
|
||||
content.wrappedJSObject.closeStream();
|
||||
|
||||
if (!aAlreadyClosed)
|
||||
yield promiseObserverCalled("recording-device-events");
|
||||
|
||||
yield promiseNoPopupNotification("webRTC-sharingDevices");
|
||||
if (!aAlreadyClosed)
|
||||
expectObserverCalled("recording-window-ended");
|
||||
|
||||
yield* assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
function loadPage(aUrl) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
|
@ -214,6 +75,7 @@ fakeLoopAboutModule.prototype = {
|
|||
getURIFlags: function (aURI) {
|
||||
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
Ci.nsIAboutModule.ALLOW_SCRIPT |
|
||||
Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD |
|
||||
Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
|
||||
}
|
||||
};
|
||||
|
@ -221,14 +83,12 @@ fakeLoopAboutModule.prototype = {
|
|||
var factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
|
||||
var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
var originalLoopCsp = Services.prefs.getCharPref(PREF_LOOP_CSP);
|
||||
var classIDLoopconversation, classIDEvil;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gBrowser.removeCurrentTab();
|
||||
kObservedTopics.forEach(topic => {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
});
|
||||
Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
|
||||
Services.prefs.setCharPref(PREF_LOOP_CSP, originalLoopCsp);
|
||||
registrar.unregisterFactory(classIDLoopconversation, factory);
|
||||
registrar.unregisterFactory(classIDEvil, factory);
|
||||
});
|
||||
|
||||
const permissionError = "error: SecurityError: The operation is insecure.";
|
||||
|
@ -238,31 +98,27 @@ var gTests = [
|
|||
{
|
||||
desc: "getUserMedia about:loopconversation shouldn't prompt",
|
||||
run: function checkAudioVideoLoop() {
|
||||
Services.prefs.setCharPref(PREF_LOOP_CSP, "default-src 'unsafe-inline'");
|
||||
|
||||
let classID = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classID, "",
|
||||
"@mozilla.org/network/protocol/about;1?what=loopconversation",
|
||||
factory);
|
||||
yield new Promise(resolve => SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
|
||||
}, resolve));
|
||||
|
||||
yield loadPage("about:loopconversation");
|
||||
|
||||
yield promiseObserverCalled("recording-device-events", () => {
|
||||
info("requesting devices");
|
||||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
info("requesting devices");
|
||||
let promise = promiseObserverCalled("recording-device-events");
|
||||
yield promiseRequestDevice(true, true);
|
||||
yield promise;
|
||||
|
||||
// Wait for the devices to actually be captured and running before
|
||||
// proceeding.
|
||||
yield promisePopupNotification("webRTC-sharingDevices");
|
||||
|
||||
is(getMediaCaptureState(), "CameraAndMicrophone",
|
||||
is((yield getMediaCaptureState()), "CameraAndMicrophone",
|
||||
"expected camera and microphone to be shared");
|
||||
|
||||
yield closeStream();
|
||||
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
Services.prefs.setCharPref(PREF_LOOP_CSP, originalLoopCsp);
|
||||
yield new Promise((resolve) => SpecialPowers.popPrefEnv(resolve));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -273,59 +129,45 @@ var gTests = [
|
|||
return;
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref(PREF_LOOP_CSP, "default-src 'unsafe-inline'");
|
||||
|
||||
let classID = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classID, "",
|
||||
"@mozilla.org/network/protocol/about;1?what=loopconversation",
|
||||
factory);
|
||||
yield new Promise(resolve => SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
|
||||
}, resolve));
|
||||
|
||||
yield loadPage("about:loopconversation");
|
||||
|
||||
yield promiseObserverCalled("getUserMedia:request", () => {
|
||||
info("requesting screen");
|
||||
content.wrappedJSObject.requestDevice(false, true, "window");
|
||||
});
|
||||
info("requesting screen");
|
||||
let promise = promiseObserverCalled("getUserMedia:request");
|
||||
yield promiseRequestDevice(false, true, null, "window");
|
||||
|
||||
// Wait for the devices to actually be captured and running before
|
||||
// proceeding.
|
||||
yield promisePopupNotification("webRTC-shareDevices");
|
||||
|
||||
isnot(getMediaCaptureState(), "Window",
|
||||
is((yield getMediaCaptureState()), "none",
|
||||
"expected camera and microphone not to be shared");
|
||||
|
||||
yield promiseMessage(permissionError, () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
});
|
||||
|
||||
expectObserverCalled("getUserMedia:response:deny");
|
||||
expectObserverCalled("recording-window-ended");
|
||||
yield expectObserverCalled("getUserMedia:response:deny");
|
||||
yield expectObserverCalled("recording-window-ended");
|
||||
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
Services.prefs.setCharPref(PREF_LOOP_CSP, originalLoopCsp);
|
||||
yield new Promise((resolve) => SpecialPowers.popPrefEnv(resolve));
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "getUserMedia about:evil should prompt",
|
||||
run: function checkAudioVideoNonLoop() {
|
||||
let classID = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classID, "",
|
||||
"@mozilla.org/network/protocol/about;1?what=evil",
|
||||
factory);
|
||||
|
||||
yield loadPage("about:evil");
|
||||
|
||||
yield promiseObserverCalled("getUserMedia:request", () => {
|
||||
info("requesting devices");
|
||||
content.wrappedJSObject.requestDevice(true, true);
|
||||
});
|
||||
let promise = promiseObserverCalled("getUserMedia:request");
|
||||
yield promiseRequestDevice(true, true);
|
||||
yield promise;
|
||||
|
||||
isnot(getMediaCaptureState(), "CameraAndMicrophone",
|
||||
is((yield getMediaCaptureState()), "none",
|
||||
"expected camera and microphone not to be shared");
|
||||
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -334,18 +176,29 @@ var gTests = [
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Services.prefs.setBoolPref(PREF_PERMISSION_FAKE, true);
|
||||
// Ensure this is always true
|
||||
Services.prefs.setBoolPref("media.getusermedia.screensharing.enabled", true);
|
||||
|
||||
gTab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = gTab;
|
||||
|
||||
kObservedTopics.forEach(topic => {
|
||||
Services.obs.addObserver(observer, topic, false);
|
||||
});
|
||||
gTab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
|
||||
|
||||
classIDLoopconversation = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classIDLoopconversation, "",
|
||||
"@mozilla.org/network/protocol/about;1?what=loopconversation",
|
||||
factory);
|
||||
|
||||
classIDEvil = Cc["@mozilla.org/uuid-generator;1"]
|
||||
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
registrar.registerFactory(classIDEvil, "",
|
||||
"@mozilla.org/network/protocol/about;1?what=evil",
|
||||
factory);
|
||||
|
||||
Task.spawn(function () {
|
||||
yield new Promise(resolve => SpecialPowers.pushPrefEnv({
|
||||
"set": [[PREF_PERMISSION_FAKE, true],
|
||||
["media.getusermedia.screensharing.enabled", true]],
|
||||
}, resolve));
|
||||
|
||||
for (let test of gTests) {
|
||||
info(test.desc);
|
||||
yield test.run();
|
||||
|
@ -358,9 +211,3 @@ function test() {
|
|||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
function wait(time) {
|
||||
let deferred = Promise.defer();
|
||||
setTimeout(deferred.resolve, time);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
|
@ -49,13 +49,20 @@ addMessageListener("Test:ExpectNoObserverCalled", data => {
|
|||
function _getMediaCaptureState() {
|
||||
let hasVideo = {};
|
||||
let hasAudio = {};
|
||||
MediaManagerService.mediaCaptureWindowState(content, hasVideo, hasAudio);
|
||||
let hasScreenShare = {};
|
||||
let hasWindowShare = {};
|
||||
MediaManagerService.mediaCaptureWindowState(content, hasVideo, hasAudio,
|
||||
hasScreenShare, hasWindowShare);
|
||||
if (hasVideo.value && hasAudio.value)
|
||||
return "CameraAndMicrophone";
|
||||
if (hasVideo.value)
|
||||
return "Camera";
|
||||
if (hasAudio.value)
|
||||
return "Microphone";
|
||||
if (hasScreenShare.value)
|
||||
return "Screen";
|
||||
if (hasWindowShare.value)
|
||||
return "Window";
|
||||
return "none";
|
||||
}
|
||||
|
||||
|
|
|
@ -161,15 +161,15 @@ function getMediaCaptureState() {
|
|||
});
|
||||
}
|
||||
|
||||
function promiseRequestDevice(aRequestAudio, aRequestVideo, aFrameId) {
|
||||
function promiseRequestDevice(aRequestAudio, aRequestVideo, aFrameId, aType) {
|
||||
info("requesting devices");
|
||||
return ContentTask.spawn(gBrowser.selectedBrowser,
|
||||
{aRequestAudio, aRequestVideo, aFrameId},
|
||||
{aRequestAudio, aRequestVideo, aFrameId, aType},
|
||||
function*(args) {
|
||||
let global = content.wrappedJSObject;
|
||||
if (args.aFrameId)
|
||||
global = global.document.getElementById(args.aFrameId).contentWindow;
|
||||
global.requestDevice(args.aRequestAudio, args.aRequestVideo);
|
||||
global.requestDevice(args.aRequestAudio, args.aRequestVideo, args.aType);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ BrowserGlue.prototype = {
|
|||
this._isPlacesShutdownObserver = true;
|
||||
os.addObserver(this, "handle-xul-text-link", false);
|
||||
os.addObserver(this, "profile-before-change", false);
|
||||
if (AppConstants.MOZ_SERVICES_HEALTHREPORT) {
|
||||
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
|
||||
os.addObserver(this, "keyword-search", false);
|
||||
}
|
||||
os.addObserver(this, "browser-search-engine-modified", false);
|
||||
|
@ -594,7 +594,7 @@ BrowserGlue.prototype = {
|
|||
os.removeObserver(this, "places-shutdown");
|
||||
os.removeObserver(this, "handle-xul-text-link");
|
||||
os.removeObserver(this, "profile-before-change");
|
||||
if (AppConstants.MOZ_SERVICES_HEALTHREPORT) {
|
||||
if (AppConstants.MOZ_TELEMETRY_REPORTING) {
|
||||
os.removeObserver(this, "keyword-search");
|
||||
}
|
||||
os.removeObserver(this, "browser-search-engine-modified");
|
||||
|
@ -1141,19 +1141,24 @@ BrowserGlue.prototype = {
|
|||
|
||||
// For any add-ons that were installed disabled and can be enabled offer
|
||||
// them to the user.
|
||||
let changedIDs = AddonManager.getStartupChanges(AddonManager.STARTUP_CHANGE_INSTALLED);
|
||||
if (changedIDs.length > 0) {
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
AddonManager.getAddonsByIDs(changedIDs, function(aAddons) {
|
||||
aAddons.forEach(function(aAddon) {
|
||||
// If the add-on isn't user disabled or can't be enabled then skip it.
|
||||
if (!aAddon.userDisabled || !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE))
|
||||
return;
|
||||
let win = RecentWindow.getMostRecentBrowserWindow();
|
||||
AddonManager.getAllAddons(addons => {
|
||||
for (let addon of addons) {
|
||||
// If this add-on has already seen (or seen is undefined for non-XPI
|
||||
// add-ons) then skip it.
|
||||
if (addon.seen !== false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
win.openUILinkIn("about:newaddon?id=" + aAddon.id, "tab");
|
||||
})
|
||||
});
|
||||
}
|
||||
// If this add-on cannot be enabled (either already enabled or
|
||||
// appDisabled) then skip it.
|
||||
if (!(addon.permissions & AddonManager.PERM_CAN_ENABLE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
win.openUILinkIn("about:newaddon?id=" + addon.id, "tab");
|
||||
}
|
||||
});
|
||||
|
||||
let signingRequired;
|
||||
if (AppConstants.MOZ_REQUIRE_SIGNING) {
|
||||
|
|
|
@ -350,7 +350,9 @@ var withBookmarksDialog = Task.async(function* (autoCancel, openFn, taskFn) {
|
|||
*
|
||||
* @param selector
|
||||
* Valid selector syntax
|
||||
* @return the target DOM node.
|
||||
* @return Promise
|
||||
* Returns a Promise that resolves once the context menu has been
|
||||
* opened.
|
||||
*/
|
||||
var openContextMenuForContentSelector = Task.async(function* (browser, selector) {
|
||||
info("wait for the context menu");
|
||||
|
@ -372,8 +374,6 @@ var openContextMenuForContentSelector = Task.async(function* (browser, selector)
|
|||
1, 0, false, 0, 0, true);
|
||||
});
|
||||
yield contextPromise;
|
||||
|
||||
return gContextMenuContentData.popupNode;
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,7 +44,7 @@ var gAdvancedPane = {
|
|||
this.initSubmitCrashes();
|
||||
#endif
|
||||
this.initTelemetry();
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
this.initSubmitHealthReport();
|
||||
#endif
|
||||
this.updateOnScreenKeyboardVisibility();
|
||||
|
@ -56,7 +56,7 @@ var gAdvancedPane = {
|
|||
gAdvancedPane.updateHardwareAcceleration);
|
||||
setEventListener("advancedPrefs", "select",
|
||||
gAdvancedPane.tabSelectionChanged);
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
setEventListener("submitHealthReportBox", "command",
|
||||
gAdvancedPane.updateSubmitHealthReport);
|
||||
#endif
|
||||
|
@ -289,7 +289,7 @@ var gAdvancedPane = {
|
|||
#endif
|
||||
},
|
||||
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
/**
|
||||
* Initialize the health report service reference and checkbox.
|
||||
*/
|
||||
|
|
|
@ -199,7 +199,7 @@
|
|||
#ifdef MOZ_DATA_REPORTING
|
||||
<!-- Data Choices -->
|
||||
<tabpanel id="dataChoicesPanel" orient="vertical">
|
||||
#ifdef MOZ_SERVICES_HEALTHREPORT
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<groupbox>
|
||||
<caption>
|
||||
<checkbox id="submitHealthReportBox" label="&enableHealthReport.label;"
|
||||
|
@ -212,7 +212,6 @@
|
|||
<label id="FHRLearnMore"
|
||||
class="text-link">&healthReportLearnMore.label;</label>
|
||||
</hbox>
|
||||
#ifdef MOZ_TELEMETRY_REPORTING
|
||||
<hbox class="indent">
|
||||
<groupbox flex="1">
|
||||
<caption>
|
||||
|
@ -228,7 +227,6 @@
|
|||
</hbox>
|
||||
</groupbox>
|
||||
</hbox>
|
||||
#endif
|
||||
</vbox>
|
||||
</groupbox>
|
||||
#endif
|
||||
|
|
|
@ -74,7 +74,7 @@ add_task(function flush_on_settabstate() {
|
|||
|
||||
// Flush all data contained in the content script but send it using
|
||||
// asynchronous messages.
|
||||
TabState.flushAsync(browser);
|
||||
TabStateFlusher.flush(browser);
|
||||
|
||||
yield promiseTabState(tab, state);
|
||||
|
||||
|
@ -101,7 +101,7 @@ add_task(function flush_on_tabclose_racy() {
|
|||
|
||||
// Flush all data contained in the content script but send it using
|
||||
// asynchronous messages.
|
||||
TabState.flushAsync(browser);
|
||||
TabStateFlusher.flush(browser);
|
||||
yield promiseRemoveTab(tab);
|
||||
|
||||
let [{state: {storage}}] = JSON.parse(ss.getClosedTabData(window));
|
||||
|
|
|
@ -38,12 +38,18 @@ add_task(function* test_bing_translation() {
|
|||
// Translating the contents of the loaded tab.
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = tab.linkedBrowser;
|
||||
let client = new BingTranslator(
|
||||
new TranslationDocument(browser.contentDocument), "fr", "en");
|
||||
let result = yield client.translate();
|
||||
|
||||
// XXXmikedeboer; here you would continue the test/ content inspection.
|
||||
Assert.ok(result, "There should be a result.");
|
||||
yield ContentTask.spawn(browser, null, function*() {
|
||||
Cu.import("resource:///modules/translation/BingTranslator.jsm");
|
||||
Cu.import("resource:///modules/translation/TranslationDocument.jsm");
|
||||
|
||||
let client = new BingTranslator(
|
||||
new TranslationDocument(content.document), "fr", "en");
|
||||
let result = yield client.translate();
|
||||
|
||||
// XXXmikedeboer; here you would continue the test/ content inspection.
|
||||
ok(result, "There should be a result");
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
@ -67,18 +73,24 @@ add_task(function* test_handling_out_of_valid_key_error() {
|
|||
// Translating the contents of the loaded tab.
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = tab.linkedBrowser;
|
||||
let client = new BingTranslator(
|
||||
new TranslationDocument(browser.contentDocument), "fr", "en");
|
||||
client._resetToken();
|
||||
try {
|
||||
yield client.translate();
|
||||
} catch (ex) {
|
||||
// It is alright that the translation fails.
|
||||
}
|
||||
client._resetToken();
|
||||
|
||||
// Checking if the client detected service and unavailable.
|
||||
Assert.ok(client._serviceUnavailable, "Service should be detected unavailable.");
|
||||
yield ContentTask.spawn(browser, null, function*() {
|
||||
Cu.import("resource:///modules/translation/BingTranslator.jsm");
|
||||
Cu.import("resource:///modules/translation/TranslationDocument.jsm");
|
||||
|
||||
let client = new BingTranslator(
|
||||
new TranslationDocument(content.document), "fr", "en");
|
||||
client._resetToken();
|
||||
try {
|
||||
yield client.translate();
|
||||
} catch (ex) {
|
||||
// It is alright that the translation fails.
|
||||
}
|
||||
client._resetToken();
|
||||
|
||||
// Checking if the client detected service and unavailable.
|
||||
ok(client._serviceUnavailable, "Service should be detected unavailable.");
|
||||
});
|
||||
|
||||
// Cleaning up.
|
||||
Services.prefs.setCharPref(kClientIdPref, "testClient");
|
||||
|
|
|
@ -10,8 +10,6 @@ const kEnginePref = "browser.translation.engine";
|
|||
const kApiKeyPref = "browser.translation.yandex.apiKeyOverride";
|
||||
const kShowUIPref = "browser.translation.ui.show";
|
||||
|
||||
const {YandexTranslator} = Cu.import("resource:///modules/translation/YandexTranslator.jsm", {});
|
||||
const {TranslationDocument} = Cu.import("resource:///modules/translation/TranslationDocument.jsm", {});
|
||||
const {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const {Translation} = Cu.import("resource:///modules/translation/Translation.jsm", {});
|
||||
|
||||
|
@ -40,11 +38,17 @@ add_task(function* test_yandex_translation() {
|
|||
// Translating the contents of the loaded tab.
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = tab.linkedBrowser;
|
||||
let client = new YandexTranslator(
|
||||
new TranslationDocument(browser.contentDocument), "fr", "en");
|
||||
let result = yield client.translate();
|
||||
|
||||
Assert.ok(result, "There should be a result.");
|
||||
yield ContentTask.spawn(browser, null, function*() {
|
||||
Cu.import("resource:///modules/translation/TranslationDocument.jsm");
|
||||
Cu.import("resource:///modules/translation/YandexTranslator.jsm");
|
||||
|
||||
let client = new YandexTranslator(
|
||||
new TranslationDocument(content.document), "fr", "en");
|
||||
let result = yield client.translate();
|
||||
|
||||
ok(result, "There should be a result.");
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
|
|
|
@ -18,5 +18,4 @@ browser = true
|
|||
qemu = false
|
||||
|
||||
[chrome/content/shared/test/test_shared_all.py]
|
||||
skip-if = os == "win" # Bug 1149955
|
||||
[chrome/content/panels/test/test_desktop_all.py]
|
||||
|
|
|
@ -8402,12 +8402,6 @@ if test -n "$MOZ_SERVICES_HEALTHREPORT"; then
|
|||
AC_DEFINE(MOZ_SERVICES_HEALTHREPORT)
|
||||
fi
|
||||
|
||||
dnl Build Services metrics component
|
||||
AC_SUBST(MOZ_SERVICES_METRICS)
|
||||
if test -n "$MOZ_SERVICES_METRICS"; then
|
||||
AC_DEFINE(MOZ_SERVICES_METRICS)
|
||||
fi
|
||||
|
||||
dnl Build Notifications if required
|
||||
AC_SUBST(MOZ_SERVICES_NOTIFICATIONS)
|
||||
if test -n "$MOZ_SERVICES_NOTIFICATIONS"; then
|
||||
|
|
|
@ -136,11 +136,11 @@ function test() {
|
|||
is(gEditor.getText().search(/debugger/), -1,
|
||||
"The second source is not displayed.");
|
||||
|
||||
ok(isCaretPos(gPanel, 6),
|
||||
ok(isCaretPos(gPanel, 5),
|
||||
"Editor caret location is correct.");
|
||||
is(gEditor.getDebugLocation(), 5,
|
||||
is(gEditor.getDebugLocation(), 4,
|
||||
"Editor debugger location is correct.");
|
||||
ok(gEditor.hasLineClass(5, "debug-line"),
|
||||
ok(gEditor.hasLineClass(4, "debug-line"),
|
||||
"The debugged line is highlighted appropriately (3).");
|
||||
}
|
||||
|
||||
|
|
|
@ -131,11 +131,11 @@ function test() {
|
|||
"The second source is not displayed.");
|
||||
|
||||
// The editor's debug location takes a tick to update.
|
||||
ok(isCaretPos(gPanel, 6),
|
||||
ok(isCaretPos(gPanel, 5),
|
||||
"Editor caret location is correct.");
|
||||
is(gEditor.getDebugLocation(), 5,
|
||||
is(gEditor.getDebugLocation(), 4,
|
||||
"Editor debugger location is correct.");
|
||||
ok(gEditor.hasLineClass(5, "debug-line"),
|
||||
ok(gEditor.hasLineClass(4, "debug-line"),
|
||||
"The debugged line is highlighted appropriately.");
|
||||
|
||||
deferred.resolve();
|
||||
|
|
|
@ -36,13 +36,13 @@ function test() {
|
|||
let stepTests = [
|
||||
{key: 'VK_F11', keyRepeat: 1, caretLine: 16},
|
||||
{key: 'VK_F11', keyRepeat: 2, caretLine: 18},
|
||||
{key: 'VK_F11', keyRepeat: 2, caretLine: 27},
|
||||
{key: 'VK_F10', keyRepeat: 1, caretLine: 27},
|
||||
{key: 'VK_F11', keyRepeat: 1, caretLine: 18},
|
||||
{key: 'VK_F11', keyRepeat: 5, caretLine: 32},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 1, caretLine: 29},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 34},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 34}
|
||||
{key: 'VK_F11', keyRepeat: 2, caretLine: 26},
|
||||
{key: 'VK_F10', keyRepeat: 1, caretLine: 18},
|
||||
{key: 'VK_F11', keyRepeat: 1, caretLine: 19},
|
||||
{key: 'VK_F11', keyRepeat: 5, caretLine: 29},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 1, caretLine: 32},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 32},
|
||||
{key: 'VK_F11', modifier:'Shift', keyRepeat: 2, caretLine: 20}
|
||||
];
|
||||
// Trigger script that stops at debugger statement
|
||||
executeSoon(() => generateMouseClickInTab(gTab,
|
||||
|
|
|
@ -23,7 +23,7 @@ function test() {
|
|||
|
||||
function testNormalReturn() {
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 17).then(() => {
|
||||
waitForCaretAndScopes(gPanel, 20).then(() => {
|
||||
waitForCaretAndScopes(gPanel, 19).then(() => {
|
||||
let innerScope = gVars.getScopeAtIndex(0);
|
||||
let returnVar = innerScope.get("<return>");
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
const {Cc, Ci} = require("chrome");
|
||||
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
@ -41,7 +41,7 @@ const scratchpadProps = "chrome://devtools/locale/scratchpad.properties";
|
|||
const memoryProps = "chrome://devtools/locale/memory.properties";
|
||||
|
||||
loader.lazyGetter(this, "toolboxStrings", () => Services.strings.createBundle(toolboxProps));
|
||||
loader.lazyGetter(this, "performanceStrings",() => Services.strings.createBundle(performanceProps));
|
||||
loader.lazyGetter(this, "performanceStrings", () => Services.strings.createBundle(performanceProps));
|
||||
loader.lazyGetter(this, "webConsoleStrings", () => Services.strings.createBundle(webConsoleProps));
|
||||
loader.lazyGetter(this, "debuggerStrings", () => Services.strings.createBundle(debuggerProps));
|
||||
loader.lazyGetter(this, "styleEditorStrings", () => Services.strings.createBundle(styleEditorProps));
|
||||
|
@ -71,14 +71,14 @@ Tools.options = {
|
|||
tooltip: l10n("optionsButton.tooltip", toolboxStrings),
|
||||
inMenu: false,
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
isTargetSupported: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
return new OptionsPanel(iframeWindow, toolbox);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Tools.inspector = {
|
||||
id: "inspector",
|
||||
|
@ -93,7 +93,7 @@ Tools.inspector = {
|
|||
panelLabel: l10n("inspector.panelLabel", inspectorStrings),
|
||||
get tooltip() {
|
||||
return l10n("inspector.tooltip2", inspectorStrings,
|
||||
( osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+" ) + this.key);
|
||||
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + this.key);
|
||||
},
|
||||
inMenu: true,
|
||||
commands: [
|
||||
|
@ -127,20 +127,21 @@ Tools.webConsole = {
|
|||
panelLabel: l10n("ToolboxWebConsole.panelLabel", webConsoleStrings),
|
||||
get tooltip() {
|
||||
return l10n("ToolboxWebconsole.tooltip2", webConsoleStrings,
|
||||
( osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+" ) + this.key);
|
||||
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + this.key);
|
||||
},
|
||||
inMenu: true,
|
||||
commands: "devtools/client/webconsole/console-commands",
|
||||
|
||||
preventClosingOnKey: true,
|
||||
onkey: function(panel, toolbox) {
|
||||
if (toolbox.splitConsole)
|
||||
if (toolbox.splitConsole) {
|
||||
return toolbox.focusConsoleInput();
|
||||
}
|
||||
|
||||
panel.focusInput();
|
||||
},
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
isTargetSupported: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -163,12 +164,12 @@ Tools.jsdebugger = {
|
|||
panelLabel: l10n("ToolboxDebugger.panelLabel", debuggerStrings),
|
||||
get tooltip() {
|
||||
return l10n("ToolboxDebugger.tooltip2", debuggerStrings,
|
||||
( osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+" ) + this.key);
|
||||
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + this.key);
|
||||
},
|
||||
inMenu: true,
|
||||
commands: "devtools/client/debugger/debugger-commands",
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
isTargetSupported: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -241,7 +242,7 @@ Tools.canvasDebugger = {
|
|||
return target.hasActor("canvas") && !target.chrome;
|
||||
},
|
||||
|
||||
build: function (iframeWindow, toolbox) {
|
||||
build: function(iframeWindow, toolbox) {
|
||||
return new CanvasDebuggerPanel(iframeWindow, toolbox);
|
||||
}
|
||||
};
|
||||
|
@ -265,11 +266,11 @@ Tools.performance = {
|
|||
modifiers: "shift",
|
||||
inMenu: true,
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
isTargetSupported: function(target) {
|
||||
return target.hasActor("profiler");
|
||||
},
|
||||
|
||||
build: function (frame, target) {
|
||||
build: function(frame, target) {
|
||||
return new PerformancePanel(frame, target);
|
||||
}
|
||||
};
|
||||
|
@ -286,11 +287,11 @@ Tools.memory = {
|
|||
panelLabel: l10n("memory.panelLabel", memoryStrings),
|
||||
tooltip: l10n("memory.tooltip", memoryStrings),
|
||||
|
||||
isTargetSupported: function (target) {
|
||||
isTargetSupported: function(target) {
|
||||
return target.getTrait("heapSnapshots");
|
||||
},
|
||||
|
||||
build: function (frame, target) {
|
||||
build: function(frame, target) {
|
||||
return new MemoryPanel(frame, target);
|
||||
}
|
||||
};
|
||||
|
@ -309,7 +310,7 @@ Tools.netMonitor = {
|
|||
panelLabel: l10n("netmonitor.panelLabel", netMonitorStrings),
|
||||
get tooltip() {
|
||||
return l10n("netmonitor.tooltip2", netMonitorStrings,
|
||||
( osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+" ) + this.key);
|
||||
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + this.key);
|
||||
},
|
||||
inMenu: true,
|
||||
|
||||
|
@ -343,8 +344,7 @@ Tools.storage = {
|
|||
|
||||
isTargetSupported: function(target) {
|
||||
return target.isLocalTab ||
|
||||
( target.hasActor("storage") &&
|
||||
target.getTrait("storageInspector") );
|
||||
(target.hasActor("storage") && target.getTrait("storageInspector"));
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
|
@ -442,8 +442,7 @@ exports.defaultThemes = [
|
|||
* The key to lookup.
|
||||
* @returns A localized version of the given key.
|
||||
*/
|
||||
function l10n(name, bundle, arg)
|
||||
{
|
||||
function l10n(name, bundle, arg) {
|
||||
try {
|
||||
return arg ? bundle.formatStringFromName(name, [arg], 1)
|
||||
: bundle.GetStringFromName(name);
|
||||
|
@ -453,7 +452,6 @@ function l10n(name, bundle, arg)
|
|||
}
|
||||
}
|
||||
|
||||
function functionkey(shortkey)
|
||||
{
|
||||
function functionkey(shortkey) {
|
||||
return shortkey.split("_")[1];
|
||||
}
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
* 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/. */
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
/* FIXME: remove this globals comment and replace with import-globals-from when
|
||||
bug 1242893 is fixed */
|
||||
/* globals BrowserToolboxProcess */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { interfaces: Ci, utils: Cu } = Components;
|
||||
const kDebuggerPrefs = [
|
||||
"devtools.debugger.remote-enabled",
|
||||
"devtools.chrome.enabled"
|
||||
|
@ -10,8 +16,8 @@ const kDebuggerPrefs = [
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
|
||||
|
||||
function devtoolsCommandlineHandler() {
|
||||
}
|
||||
function devtoolsCommandlineHandler() {}
|
||||
|
||||
devtoolsCommandlineHandler.prototype = {
|
||||
handle: function(cmdLine) {
|
||||
let consoleFlag = cmdLine.handleFlag("jsconsole", false);
|
||||
|
@ -31,7 +37,7 @@ devtoolsCommandlineHandler.prototype = {
|
|||
try {
|
||||
debuggerServerFlag =
|
||||
cmdLine.handleFlagWithParam("start-debugger-server", false);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// We get an error if the option is given but not followed by a value.
|
||||
// By catching and trying again, the value is effectively optional.
|
||||
debuggerServerFlag = cmdLine.handleFlag("start-debugger-server", false);
|
||||
|
@ -51,7 +57,8 @@ devtoolsCommandlineHandler.prototype = {
|
|||
let { console } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
hudservice.toggleBrowserConsole().then(null, console.error);
|
||||
} else {
|
||||
window.focus(); // the Browser Console was already open
|
||||
// the Browser Console was already open
|
||||
window.focus();
|
||||
}
|
||||
|
||||
if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO) {
|
||||
|
@ -62,7 +69,8 @@ devtoolsCommandlineHandler.prototype = {
|
|||
// Open the toolbox on the selected tab once the browser starts up.
|
||||
handleDevToolsFlag: function() {
|
||||
Services.obs.addObserver(function onStartup(window) {
|
||||
Services.obs.removeObserver(onStartup, "browser-delayed-startup-finished");
|
||||
Services.obs.removeObserver(onStartup,
|
||||
"browser-delayed-startup-finished");
|
||||
const {gDevTools} = Cu.import("resource://devtools/client/framework/gDevTools.jsm", {});
|
||||
const {devtools} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let target = devtools.TargetFactory.forTab(window.gBrowser.selectedTab);
|
||||
|
@ -73,14 +81,16 @@ devtoolsCommandlineHandler.prototype = {
|
|||
_isRemoteDebuggingEnabled() {
|
||||
let remoteDebuggingEnabled = false;
|
||||
try {
|
||||
remoteDebuggingEnabled = kDebuggerPrefs.every((pref) => Services.prefs.getBoolPref(pref));
|
||||
remoteDebuggingEnabled = kDebuggerPrefs.every(pref => {
|
||||
return Services.prefs.getBoolPref(pref);
|
||||
});
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
return false;
|
||||
}
|
||||
if (!remoteDebuggingEnabled) {
|
||||
let errorMsg = "Could not run chrome debugger! You need the following prefs " +
|
||||
"to be set to true: " + kDebuggerPrefs.join(", ");
|
||||
let errorMsg = "Could not run chrome debugger! You need the following " +
|
||||
"prefs to be set to true: " + kDebuggerPrefs.join(", ");
|
||||
Cu.reportError(errorMsg);
|
||||
// Dump as well, as we're doing this from a commandline, make sure people
|
||||
// don't miss it:
|
||||
|
@ -131,7 +141,7 @@ devtoolsCommandlineHandler.prototype = {
|
|||
listener.portOrPath = portOrPath;
|
||||
listener.open();
|
||||
dump("Started debugger server on " + portOrPath + "\n");
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
dump("Unable to start debugger server on " + portOrPath + ": " + e);
|
||||
}
|
||||
|
||||
|
@ -140,15 +150,16 @@ devtoolsCommandlineHandler.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
helpInfo : " --jsconsole Open the Browser Console.\n" +
|
||||
" --jsdebugger Open the Browser Toolbox.\n" +
|
||||
" --devtools Open DevTools on initial load.\n" +
|
||||
" --start-debugger-server [port|path] " +
|
||||
"Start the debugger server on a TCP port or " +
|
||||
"Unix domain socket path. Defaults to TCP port 6000.\n",
|
||||
helpInfo: " --jsconsole Open the Browser Console.\n" +
|
||||
" --jsdebugger Open the Browser Toolbox.\n" +
|
||||
" --devtools Open DevTools on initial load.\n" +
|
||||
" --start-debugger-server [port|path] " +
|
||||
"Start the debugger server on a TCP port or " +
|
||||
"Unix domain socket path. Defaults to TCP port 6000.\n",
|
||||
|
||||
classID: Components.ID("{9e9a9283-0ce9-4e4a-8f1c-ba129a032c32}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([devtoolsCommandlineHandler]);
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
|
||||
[devtoolsCommandlineHandler]);
|
||||
|
|
|
@ -264,12 +264,7 @@ ToolSidebar.prototype = {
|
|||
this._tabs.set(id, tab);
|
||||
|
||||
if (selected) {
|
||||
// For some reason I don't understand, if we call this.select in this
|
||||
// event loop (after inserting the tab), the tab will never get the
|
||||
// the "selected" attribute set to true.
|
||||
this._panelDoc.defaultView.setTimeout(() => {
|
||||
this.select(id);
|
||||
}, 10);
|
||||
this._selectTabSoon(id);
|
||||
}
|
||||
|
||||
this.emit("new-tab-registered", id);
|
||||
|
@ -291,6 +286,12 @@ ToolSidebar.prototype = {
|
|||
// Find an ID for this unknown tab
|
||||
let id = tab.getAttribute("id") || "untitled-tab-" + (this.untitledTabsIndex++);
|
||||
|
||||
// If the existing tab contains the tab ID prefix, extract the ID of the
|
||||
// tab
|
||||
if (id.startsWith(this.TAB_ID_PREFIX)) {
|
||||
id = id.split(this.TAB_ID_PREFIX).pop();
|
||||
}
|
||||
|
||||
// Register the tab
|
||||
this._tabs.set(id, tab);
|
||||
this.emit("new-tab-registered", id);
|
||||
|
@ -357,6 +358,18 @@ ToolSidebar.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hack required to select a tab right after it was created.
|
||||
*
|
||||
* @param {String} id
|
||||
* The sidebar tab id to select.
|
||||
*/
|
||||
_selectTabSoon: function(id) {
|
||||
this._panelDoc.defaultView.setTimeout(() => {
|
||||
this.select(id);
|
||||
}, 0);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the id of the selected tab.
|
||||
*/
|
||||
|
@ -450,13 +463,28 @@ ToolSidebar.prototype = {
|
|||
|
||||
/**
|
||||
* Show the sidebar.
|
||||
*
|
||||
* @param {String} id
|
||||
* The sidebar tab id to select.
|
||||
*/
|
||||
show: function() {
|
||||
show: function(id) {
|
||||
if (this._width) {
|
||||
this._tabbox.width = this._width;
|
||||
}
|
||||
this._tabbox.removeAttribute("hidden");
|
||||
|
||||
// If an id is given, select the corresponding sidebar tab and record the
|
||||
// tool opened.
|
||||
if (id) {
|
||||
this._currentTool = id;
|
||||
|
||||
if (this._telemetry) {
|
||||
this._telemetry.toolOpened(this._currentTool);
|
||||
}
|
||||
|
||||
this._selectTabSoon(id);
|
||||
}
|
||||
|
||||
this.emit("show");
|
||||
},
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ const {Cu, Cc, Ci} = require("chrome");
|
|||
const Services = require("Services");
|
||||
const promise = require("promise");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools", "resource://devtools/client/framework/gDevTools.jsm");
|
||||
|
||||
exports.OptionsPanel = OptionsPanel;
|
||||
|
@ -94,32 +95,21 @@ OptionsPanel.prototype = {
|
|||
return this.toolbox.target;
|
||||
},
|
||||
|
||||
open: function() {
|
||||
let targetPromise;
|
||||
|
||||
open: Task.async(function*() {
|
||||
// For local debugging we need to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
targetPromise = this.target.makeRemote();
|
||||
} else {
|
||||
targetPromise = promise.resolve(this.target);
|
||||
yield this.target.makeRemote();
|
||||
}
|
||||
|
||||
return targetPromise.then(() => {
|
||||
this.setupToolsList();
|
||||
this.setupToolbarButtonsList();
|
||||
this.setupThemeList();
|
||||
this.updateDefaultTheme();
|
||||
}).then(() => {
|
||||
return this.populatePreferences();
|
||||
}).then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
}).then(null, function onError(aReason) {
|
||||
Cu.reportError("OptionsPanel open failed. " +
|
||||
aReason.error + ": " + aReason.message);
|
||||
});
|
||||
},
|
||||
this.setupToolsList();
|
||||
this.setupToolbarButtonsList();
|
||||
this.setupThemeList();
|
||||
this.updateDefaultTheme();
|
||||
yield this.populatePreferences();
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
}),
|
||||
|
||||
_addListeners: function() {
|
||||
gDevTools.on("pref-changed", this._prefChanged);
|
||||
|
|
|
@ -963,13 +963,15 @@ PropertyView.prototype = {
|
|||
};
|
||||
this.element.addEventListener("keydown", this.onKeyDown, false);
|
||||
|
||||
let nameContainer = doc.createElementNS(HTML_NS, "div");
|
||||
nameContainer.className = "property-name-container";
|
||||
this.element.appendChild(nameContainer);
|
||||
|
||||
// Build the twisty expand/collapse
|
||||
this.matchedExpander = doc.createElementNS(HTML_NS, "div");
|
||||
this.matchedExpander.className = "expander theme-twisty";
|
||||
this.matchedExpander.addEventListener("click", this.onMatchedToggle, false);
|
||||
this.element.appendChild(this.matchedExpander);
|
||||
|
||||
this.focusElement = () => this.element.focus();
|
||||
nameContainer.appendChild(this.matchedExpander);
|
||||
|
||||
// Build the style name element
|
||||
this.nameNode = doc.createElementNS(HTML_NS, "div");
|
||||
|
@ -981,7 +983,11 @@ PropertyView.prototype = {
|
|||
// Make it hand over the focus to the container
|
||||
this.onFocus = () => this.element.focus();
|
||||
this.nameNode.addEventListener("click", this.onFocus, false);
|
||||
this.element.appendChild(this.nameNode);
|
||||
nameContainer.appendChild(this.nameNode);
|
||||
|
||||
let valueContainer = doc.createElementNS(HTML_NS, "div");
|
||||
valueContainer.className = "property-value-container";
|
||||
this.element.appendChild(valueContainer);
|
||||
|
||||
// Build the style value element
|
||||
this.valueNode = doc.createElementNS(HTML_NS, "div");
|
||||
|
@ -992,7 +998,7 @@ PropertyView.prototype = {
|
|||
this.valueNode.setAttribute("dir", "ltr");
|
||||
// Make it hand over the focus to the container
|
||||
this.valueNode.addEventListener("click", this.onFocus, false);
|
||||
this.element.appendChild(this.valueNode);
|
||||
valueContainer.appendChild(this.valueNode);
|
||||
|
||||
return this.element;
|
||||
},
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/styleinspector.dtd">
|
||||
%inspectorDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
<!ELEMENT loop ANY>
|
||||
<!ATTLIST li foreach CDATA #IMPLIED>
|
||||
<!ATTLIST div foreach CDATA #IMPLIED>
|
||||
<!ATTLIST loop foreach CDATA #IMPLIED>
|
||||
<!ATTLIST a target CDATA #IMPLIED>
|
||||
<!ATTLIST a __pathElement CDATA #IMPLIED>
|
||||
<!ATTLIST div _id CDATA #IMPLIED>
|
||||
<!ATTLIST div save CDATA #IMPLIED>
|
||||
<!ATTLIST table save CDATA #IMPLIED>
|
||||
<!ATTLIST loop if CDATA #IMPLIED>
|
||||
<!ATTLIST tr if CDATA #IMPLIED>
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
class="theme-sidebar">
|
||||
|
||||
<head>
|
||||
|
||||
<title>&computedViewTitle;</title>
|
||||
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/computed.css" type="text/css"/>
|
||||
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.setPanel = function(panel, iframe) {
|
||||
let {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
|
||||
this.computedview = new ComputedViewTool(panel, window);
|
||||
}
|
||||
window.onunload = function() {
|
||||
if (this.computedview) {
|
||||
this.computedview.destroy();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;">
|
||||
|
||||
<div id="root" class="devtools-monospace">
|
||||
<div class="devtools-toolbar">
|
||||
<div class="devtools-searchbox">
|
||||
<input id="computedview-searchbox"
|
||||
class="devtools-searchinput devtools-rule-searchbox"
|
||||
type="search" placeholder="&filterStylesPlaceholder;"/>
|
||||
<button id="computedview-searchinput-clear" class="devtools-searchinput-clear"></button>
|
||||
</div>
|
||||
<xul:checkbox id="browser-style-checkbox"
|
||||
class="includebrowserstyles"
|
||||
checked="false" label="&browserStylesLabel;"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The output from #templateProperty (below) is appended here. -->
|
||||
<div id="propertyContainer" class="devtools-monospace">
|
||||
</div>
|
||||
|
||||
<!-- When no properties are found the following block is displayed. -->
|
||||
<div id="noResults" hidden="">
|
||||
&noPropertiesFound;
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -22,17 +22,17 @@ add_task(function*() {
|
|||
|
||||
info("Checking the property itself");
|
||||
let container = getComputedViewPropertyView(view, "color").valueNode;
|
||||
checkColorCycling(container, inspector);
|
||||
checkColorCycling(container, view);
|
||||
|
||||
info("Checking matched selectors");
|
||||
container = yield getComputedViewMatchedRules(view, "color");
|
||||
checkColorCycling(container, inspector);
|
||||
checkColorCycling(container, view);
|
||||
});
|
||||
|
||||
function checkColorCycling(container, inspector) {
|
||||
function checkColorCycling(container, view) {
|
||||
let swatch = container.querySelector(".computedview-colorswatch");
|
||||
let valueNode = container.querySelector(".computedview-color");
|
||||
let win = inspector.sidebar.getWindowForTab("computedview");
|
||||
let win = view.styleWindow;
|
||||
|
||||
// "Authored" (default; currently the computed value)
|
||||
is(valueNode.textContent, "rgb(255, 0, 0)",
|
||||
|
|
|
@ -37,8 +37,8 @@ add_task(function*() {
|
|||
is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
|
||||
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
|
||||
is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
|
||||
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
|
||||
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
|
||||
is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
|
||||
is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
|
||||
is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
|
||||
|
||||
info("Closing context menu");
|
||||
|
|
|
@ -53,7 +53,7 @@ function* checkCopySelection(view) {
|
|||
|
||||
let range = contentDocument.createRange();
|
||||
range.setStart(props[1], 0);
|
||||
range.setEnd(props[3], 3);
|
||||
range.setEnd(props[3], 2);
|
||||
contentDocument.defaultView.getSelection().addRange(range);
|
||||
|
||||
info("Checking that cssHtmlTree.siBoundCopy() returns the correct " +
|
||||
|
|
|
@ -19,11 +19,11 @@ registerCleanupFunction(() => {
|
|||
* view is visible and ready
|
||||
*/
|
||||
function openComputedView() {
|
||||
return openInspectorSidebarTab("computedview").then(objects => {
|
||||
return openInspectorSidebarTab("computedview").then(({toolbox, inspector}) => {
|
||||
return {
|
||||
toolbox: objects.toolbox,
|
||||
inspector: objects.inspector,
|
||||
view: objects.view.view
|
||||
toolbox,
|
||||
inspector,
|
||||
view: inspector.computedview.view
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var { utils: Cu } = Components;
|
||||
const {Cu} = require("chrome");
|
||||
const {setTimeout, clearTimeout} =
|
||||
Cu.import("resource://gre/modules/Timer.jsm", {});
|
||||
|
||||
const DEFAULT_PREVIEW_TEXT = "Abc";
|
||||
const PREVIEW_UPDATE_DELAY = 150;
|
||||
|
||||
|
@ -16,8 +19,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "console",
|
||||
"resource://gre/modules/Console.jsm");
|
||||
|
||||
function FontInspector(inspector, window)
|
||||
{
|
||||
function FontInspector(inspector, window) {
|
||||
this.inspector = inspector;
|
||||
this.pageStyle = this.inspector.pageStyle;
|
||||
this.chromeDoc = window.document;
|
||||
|
@ -32,10 +34,11 @@ FontInspector.prototype = {
|
|||
this.inspector.selection.on("new-node", this.onNewNode);
|
||||
this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
|
||||
this.showAll = this.showAll.bind(this);
|
||||
this.showAllButton = this.chromeDoc.getElementById("showall");
|
||||
this.showAllButton = this.chromeDoc.getElementById("font-showall");
|
||||
this.showAllButton.addEventListener("click", this.showAll);
|
||||
this.previewTextChanged = this.previewTextChanged.bind(this);
|
||||
this.previewInput = this.chromeDoc.getElementById("preview-text-input");
|
||||
this.previewInput =
|
||||
this.chromeDoc.getElementById("font-preview-text-input");
|
||||
this.previewInput.addEventListener("input", this.previewTextChanged);
|
||||
|
||||
// Listen for theme changes as the color of the previews depend on the theme
|
||||
|
@ -123,7 +126,8 @@ FontInspector.prototype = {
|
|||
* Hide the font list. No node are selected.
|
||||
*/
|
||||
dim: function() {
|
||||
this.chromeDoc.body.classList.add("dim");
|
||||
let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
|
||||
panel.classList.add("dim");
|
||||
this.clear();
|
||||
},
|
||||
|
||||
|
@ -131,7 +135,8 @@ FontInspector.prototype = {
|
|||
* Show the font list. A node is selected.
|
||||
*/
|
||||
undim: function() {
|
||||
this.chromeDoc.body.classList.remove("dim");
|
||||
let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
|
||||
panel.classList.remove("dim");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -146,12 +151,13 @@ FontInspector.prototype = {
|
|||
*/
|
||||
update: Task.async(function*(showAllFonts) {
|
||||
let node = this.inspector.selection.nodeFront;
|
||||
let panel = this.chromeDoc.getElementById("sidebar-panel-fontinspector");
|
||||
|
||||
if (!node ||
|
||||
!this.isActive() ||
|
||||
!this.inspector.selection.isConnected() ||
|
||||
!this.inspector.selection.isElementNode() ||
|
||||
this.chromeDoc.body.classList.contains("dim")) {
|
||||
panel.classList.contains("dim")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -205,7 +211,7 @@ FontInspector.prototype = {
|
|||
* Display the information of one font.
|
||||
*/
|
||||
render: function(font) {
|
||||
let s = this.chromeDoc.querySelector("#template > section");
|
||||
let s = this.chromeDoc.querySelector("#font-template > section");
|
||||
s = s.cloneNode(true);
|
||||
|
||||
s.querySelector(".font-name").textContent = font.name;
|
||||
|
@ -247,12 +253,4 @@ FontInspector.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
window.setPanel = function(panel) {
|
||||
window.fontInspector = new FontInspector(panel, window);
|
||||
};
|
||||
|
||||
window.onunload = function() {
|
||||
if (window.fontInspector) {
|
||||
window.fontInspector.destroy();
|
||||
}
|
||||
};
|
||||
exports.FontInspector = FontInspector;
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % fontinspectorDTD SYSTEM "chrome://devtools/locale/font-inspector.dtd" >
|
||||
%fontinspectorDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>&fontInspectorTitle;</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/fonts.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
</head>
|
||||
<body class="theme-sidebar devtools-monospace" role="application">
|
||||
<script type="application/javascript;version=1.8" src="fonts.js"></script>
|
||||
<div>
|
||||
<div class="devtools-toolbar preview-input-toolbar">
|
||||
<div class="devtools-searchbox">
|
||||
<input id="preview-text-input"
|
||||
class="devtools-textinput"
|
||||
placeholder="&previewHint;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="root">
|
||||
<ul id="all-fonts"></ul>
|
||||
<button id="showall">&showAllFonts;</button>
|
||||
</div>
|
||||
<div id="template">
|
||||
<section class="font">
|
||||
<div class="font-preview-container">
|
||||
<img class="font-preview"></img>
|
||||
</div>
|
||||
<div class="font-info">
|
||||
<h1 class="font-name"></h1>
|
||||
<span class="font-is-local">&system;</span>
|
||||
<span class="font-is-remote">&remote;</span>
|
||||
<p class="font-format-url">
|
||||
<input readonly="readonly" class="font-url"></input>
|
||||
<span class="font-format"></span>
|
||||
</p>
|
||||
<p class="font-css">&usedAs; "<span class="font-css-name"></span>"</p>
|
||||
<pre class="font-css-code"></pre>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -82,7 +82,7 @@ function* testShowAllFonts(inspector, viewDoc) {
|
|||
info("testing showing all fonts");
|
||||
|
||||
let updated = inspector.once("fontinspector-updated");
|
||||
viewDoc.querySelector("#showall").click();
|
||||
viewDoc.querySelector("#font-showall").click();
|
||||
yield updated;
|
||||
|
||||
// shouldn't change the node selection
|
||||
|
|
|
@ -21,7 +21,7 @@ add_task(function*() {
|
|||
let onUpdated = inspector.once("fontinspector-updated");
|
||||
|
||||
info("Clicking 'Select all' button.");
|
||||
viewDoc.getElementById("showall").click();
|
||||
viewDoc.getElementById("font-showall").click();
|
||||
|
||||
info("Waiting for font-inspector to update.");
|
||||
yield onUpdated;
|
||||
|
|
|
@ -36,7 +36,7 @@ var openFontInspectorForURL = Task.async(function*(url) {
|
|||
return {
|
||||
toolbox,
|
||||
inspector,
|
||||
view: inspector.sidebar.getWindowForTab("fontinspector").fontInspector
|
||||
view: inspector.fontInspector
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -51,7 +51,7 @@ function* updatePreviewText(view, text) {
|
|||
info(`Changing the preview text to '${text}'`);
|
||||
|
||||
let doc = view.chromeDoc;
|
||||
let input = doc.getElementById("preview-text-input");
|
||||
let input = doc.getElementById("font-preview-text-input");
|
||||
let update = view.inspector.once("fontinspector-updated");
|
||||
|
||||
info("Focusing the input field.");
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
* 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/. */
|
||||
|
||||
const {Cc, Ci, Cu, Cr} = require("chrome");
|
||||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
|
@ -19,6 +21,10 @@ loader.lazyGetter(this, "MarkupView", () => require("devtools/client/inspector/m
|
|||
loader.lazyGetter(this, "HTMLBreadcrumbs", () => require("devtools/client/inspector/breadcrumbs").HTMLBreadcrumbs);
|
||||
loader.lazyGetter(this, "ToolSidebar", () => require("devtools/client/framework/sidebar").ToolSidebar);
|
||||
loader.lazyGetter(this, "InspectorSearch", () => require("devtools/client/inspector/inspector-search").InspectorSearch);
|
||||
loader.lazyGetter(this, "RuleViewTool", () => require("devtools/client/inspector/rules/rules").RuleViewTool);
|
||||
loader.lazyGetter(this, "ComputedViewTool", () => require("devtools/client/inspector/computed/computed").ComputedViewTool);
|
||||
loader.lazyGetter(this, "FontInspector", () => require("devtools/client/inspector/fonts/fonts").FontInspector);
|
||||
loader.lazyGetter(this, "LayoutView", () => require("devtools/client/inspector/layout/layout").LayoutView);
|
||||
|
||||
loader.lazyGetter(this, "strings", () => {
|
||||
return Services.strings.createBundle("chrome://devtools/locale/inspector.properties");
|
||||
|
@ -352,23 +358,16 @@ InspectorPanel.prototype = {
|
|||
|
||||
this.sidebar.on("select", this._setDefaultSidebar);
|
||||
|
||||
this.sidebar.addTab("ruleview",
|
||||
"chrome://devtools/content/inspector/rules/rules.xhtml",
|
||||
"ruleview" == defaultTab);
|
||||
this.ruleview = new RuleViewTool(this, this.panelWin);
|
||||
this.computedview = new ComputedViewTool(this, this.panelWin);
|
||||
|
||||
this.sidebar.addTab("computedview",
|
||||
"chrome://devtools/content/inspector/computed/computed.xhtml",
|
||||
"computedview" == defaultTab);
|
||||
|
||||
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled") && this.canGetUsedFontFaces) {
|
||||
this.sidebar.addTab("fontinspector",
|
||||
"chrome://devtools/content/inspector/fonts/fonts.xhtml",
|
||||
"fontinspector" == defaultTab);
|
||||
if (Services.prefs.getBoolPref("devtools.fontinspector.enabled") &&
|
||||
this.canGetUsedFontFaces) {
|
||||
this.fontInspector = new FontInspector(this, this.panelWin);
|
||||
this.panelDoc.getElementById("sidebar-tab-fontinspector").hidden = false;
|
||||
}
|
||||
|
||||
this.sidebar.addTab("layoutview",
|
||||
"chrome://devtools/content/inspector/layout/layout.xhtml",
|
||||
"layoutview" == defaultTab);
|
||||
this.layoutview = new LayoutView(this, this.panelWin);
|
||||
|
||||
if (this.target.form.animationsActor) {
|
||||
this.sidebar.addTab("animationinspector",
|
||||
|
@ -376,7 +375,7 @@ InspectorPanel.prototype = {
|
|||
"animationinspector" == defaultTab);
|
||||
}
|
||||
|
||||
this.sidebar.show();
|
||||
this.sidebar.show(defaultTab);
|
||||
|
||||
this.setupSidebarToggle();
|
||||
},
|
||||
|
@ -586,6 +585,22 @@ InspectorPanel.prototype = {
|
|||
this._toolbox.off("select", this.updateDebuggerPausedWarning);
|
||||
this._toolbox.off("host-changed", this.onToolboxHostChanged);
|
||||
|
||||
if (this.ruleview) {
|
||||
this.ruleview.destroy();
|
||||
}
|
||||
|
||||
if (this.computedview) {
|
||||
this.computedview.destroy();
|
||||
}
|
||||
|
||||
if (this.fontInspector) {
|
||||
this.fontInspector.destroy();
|
||||
}
|
||||
|
||||
if (this.layoutview) {
|
||||
this.layoutview.destroy();
|
||||
}
|
||||
|
||||
this.sidebar.off("select", this._setDefaultSidebar);
|
||||
let sidebarDestroyer = this.sidebar.destroy();
|
||||
this.sidebar = null;
|
||||
|
|
|
@ -8,12 +8,20 @@
|
|||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/inspector.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/rules.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/computed.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/fonts.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/layout.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/inspector.dtd" >
|
||||
%inspectorDTD;
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/inspector.dtd"> %inspectorDTD;
|
||||
<!ENTITY % styleinspectorDTD SYSTEM "chrome://devtools/locale/styleinspector.dtd"> %styleinspectorDTD;
|
||||
<!ENTITY % fontinspectorDTD SYSTEM "chrome://devtools/locale/font-inspector.dtd"> %fontinspectorDTD;
|
||||
<!ENTITY % layoutviewDTD SYSTEM "chrome://devtools/locale/layoutview.dtd"> %layoutviewDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
|
@ -169,8 +177,145 @@
|
|||
</vbox>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<tabbox id="inspector-sidebar" handleCtrlTab="false" class="devtools-sidebar-tabs" hidden="true">
|
||||
<tabs/>
|
||||
<tabpanels flex="1"/>
|
||||
<tabs>
|
||||
<tab id="sidebar-tab-ruleview"
|
||||
label="&ruleViewTitle;"
|
||||
crop="end"/>
|
||||
<tab id="sidebar-tab-computedview"
|
||||
label="&computedViewTitle;"
|
||||
crop="end"/>
|
||||
<tab id="sidebar-tab-fontinspector"
|
||||
label="&fontInspectorTitle;"
|
||||
crop="end"
|
||||
hidden="true"/>
|
||||
<tab id="sidebar-tab-layoutview"
|
||||
label="&layoutViewTitle;"
|
||||
crop="end"/>
|
||||
</tabs>
|
||||
<tabpanels flex="1">
|
||||
<tabpanel id="sidebar-panel-ruleview" class="devtools-monospace theme-sidebar">
|
||||
<html:div id="ruleview-toolbar" class="devtools-toolbar devtools-sidebar-toolbar">
|
||||
<html:div class="devtools-searchbox">
|
||||
<html:input id="ruleview-searchbox"
|
||||
class="devtools-searchinput devtools-rule-searchbox"
|
||||
type="search"
|
||||
placeholder="&filterStylesPlaceholder;"/>
|
||||
<html:button id="ruleview-searchinput-clear" class="devtools-searchinput-clear"></html:button>
|
||||
</html:div>
|
||||
<html:button id="ruleview-add-rule-button" title="&addRuleButtonTooltip;" class="devtools-button"></html:button>
|
||||
<html:button id="pseudo-class-panel-toggle" title="&togglePseudoClassPanel;" class="devtools-button"></html:button>
|
||||
</html:div>
|
||||
<html:div id="pseudo-class-panel" class="devtools-toolbar devtools-sidebar-toolbar" hidden="true" tabindex="-1">
|
||||
<html:label><html:input id="pseudo-hover-toggle" type="checkbox" value=":hover" tabindex="-1" />:hover</html:label>
|
||||
<html:label><html:input id="pseudo-active-toggle" type="checkbox" value=":active" tabindex="-1" />:active</html:label>
|
||||
<html:label><html:input id="pseudo-focus-toggle" type="checkbox" value=":focus" tabindex="-1" />:focus</html:label>
|
||||
</html:div>
|
||||
|
||||
<html:div id="ruleview-container" class="ruleview">
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-computedview" class="devtools-monospace theme-sidebar">
|
||||
<html:div class="devtools-toolbar devtools-sidebar-toolbar">
|
||||
<html:div class="devtools-searchbox">
|
||||
<html:input id="computedview-searchbox"
|
||||
class="devtools-searchinput devtools-rule-searchbox"
|
||||
type="search"
|
||||
placeholder="&filterStylesPlaceholder;"/>
|
||||
<html:button id="computedview-searchinput-clear" class="devtools-searchinput-clear"></html:button>
|
||||
</html:div>
|
||||
<checkbox id="browser-style-checkbox"
|
||||
class="includebrowserstyles"
|
||||
checked="false"
|
||||
label="&browserStylesLabel;"/>
|
||||
</html:div>
|
||||
|
||||
<html:div id="propertyContainer">
|
||||
</html:div>
|
||||
|
||||
<html:div id="noResults" hidden="">
|
||||
&noPropertiesFound;
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-fontinspector" class="devtools-monospace theme-sidebar">
|
||||
<html:div class="devtools-toolbar devtools-sidebar-toolbar">
|
||||
<html:div class="devtools-searchbox">
|
||||
<html:input id="font-preview-text-input"
|
||||
class="devtools-textinput"
|
||||
type="search"
|
||||
placeholder="&previewHint;"/>
|
||||
</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-container">
|
||||
<html:ul id="all-fonts"></html:ul>
|
||||
<html:button id="font-showall">&showAllFonts;</html:button>
|
||||
</html:div>
|
||||
|
||||
<html:div id="font-template">
|
||||
<html:section class="font">
|
||||
<html:div class="font-preview-container">
|
||||
<html:img class="font-preview"></html:img>
|
||||
</html:div>
|
||||
<html:div class="font-info">
|
||||
<html:h1 class="font-name"></html:h1>
|
||||
<html:span class="font-is-local">&system;</html:span>
|
||||
<html:span class="font-is-remote">&remote;</html:span>
|
||||
<html:p class="font-format-url">
|
||||
<html:input readonly="readonly" class="font-url"></html:input>
|
||||
<html:span class="font-format"></html:span>
|
||||
</html:p>
|
||||
<html:p class="font-css">&usedAs; "<html:span class="font-css-name"></html:span>"</html:p>
|
||||
<html:pre class="font-css-code"></html:pre>
|
||||
</html:div>
|
||||
</html:section>
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
|
||||
<tabpanel id="sidebar-panel-layoutview" class="devtools-monospace theme-sidebar">
|
||||
<html:div id="layout-container">
|
||||
<html:p id="layout-header">
|
||||
<html:span id="layout-element-size"></html:span><html:span id="layout-element-position"></html:span>
|
||||
</html:p>
|
||||
|
||||
<html:div id="layout-main">
|
||||
<html:span class="layout-legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</html:span>
|
||||
<html:div id="layout-margins" data-box="margin" title="&margin.tooltip;">
|
||||
<html:span class="layout-legend" data-box="border" title="&border.tooltip;">&border.tooltip;</html:span>
|
||||
<html:div id="layout-borders" data-box="border" title="&border.tooltip;">
|
||||
<html:span class="layout-legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</html:span>
|
||||
<html:div id="layout-padding" data-box="padding" title="&padding.tooltip;">
|
||||
<html:div id="layout-content" data-box="content" title="&content.tooltip;">
|
||||
</html:div>
|
||||
</html:div>
|
||||
</html:div>
|
||||
</html:div>
|
||||
|
||||
<html:p class="layout-border layout-top"><html:span data-box="border" class="layout-editable" title="border-top"></html:span></html:p>
|
||||
<html:p class="layout-border layout-right"><html:span data-box="border" class="layout-editable" title="border-right"></html:span></html:p>
|
||||
<html:p class="layout-border layout-bottom"><html:span data-box="border" class="layout-editable" title="border-bottom"></html:span></html:p>
|
||||
<html:p class="layout-border layout-left"><html:span data-box="border" class="layout-editable" title="border-left"></html:span></html:p>
|
||||
|
||||
<html:p class="layout-margin layout-top"><html:span data-box="margin" class="layout-editable" title="margin-top"></html:span></html:p>
|
||||
<html:p class="layout-margin layout-right"><html:span data-box="margin" class="layout-editable" title="margin-right"></html:span></html:p>
|
||||
<html:p class="layout-margin layout-bottom"><html:span data-box="margin" class="layout-editable" title="margin-bottom"></html:span></html:p>
|
||||
<html:p class="layout-margin layout-left"><html:span data-box="margin" class="layout-editable" title="margin-left"></html:span></html:p>
|
||||
|
||||
<html:p class="layout-padding layout-top"><html:span data-box="padding" class="layout-editable" title="padding-top"></html:span></html:p>
|
||||
<html:p class="layout-padding layout-right"><html:span data-box="padding" class="layout-editable" title="padding-right"></html:span></html:p>
|
||||
<html:p class="layout-padding layout-bottom"><html:span data-box="padding" class="layout-editable" title="padding-bottom"></html:span></html:p>
|
||||
<html:p class="layout-padding layout-left"><html:span data-box="padding" class="layout-editable" title="padding-left"></html:span></html:p>
|
||||
|
||||
<html:p class="layout-size"><html:span data-box="content" title="&content.tooltip;"></html:span></html:p>
|
||||
</html:div>
|
||||
|
||||
<html:div style="display: none">
|
||||
<html:p id="layout-dummy"></html:p>
|
||||
</html:div>
|
||||
</html:div>
|
||||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
</box>
|
||||
</window>
|
||||
|
|
|
@ -6,16 +6,15 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var {utils: Cu, interfaces: Ci, classes: Cc} = Components;
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
const {InplaceEditor, editableItem} =
|
||||
require("devtools/client/shared/inplace-editor");
|
||||
const {ReflowFront} = require("devtools/server/actors/layout");
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
Cu.import("resource://gre/modules/Console.jsm");
|
||||
Cu.import("resource://devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
|
||||
const {InplaceEditor, editableItem} = require("devtools/client/shared/inplace-editor");
|
||||
const {ReflowFront} = require("devtools/server/actors/layout");
|
||||
|
||||
const STRINGS_URI = "chrome://devtools/locale/shared.properties";
|
||||
const SHARED_L10N = new ViewHelpers.L10N(STRINGS_URI);
|
||||
const NUMERIC = /^-?[\d\.]+$/;
|
||||
|
@ -60,7 +59,7 @@ EditingSession.prototype = {
|
|||
// Create a hidden element for getPropertyFromRule to use
|
||||
let div = this._doc.createElement("div");
|
||||
div.setAttribute("style", "display: none");
|
||||
this._doc.body.appendChild(div);
|
||||
this._doc.getElementById("sidebar-panel-layoutview").appendChild(div);
|
||||
this._element = this._doc.createElement("p");
|
||||
div.appendChild(this._element);
|
||||
|
||||
|
@ -137,10 +136,9 @@ EditingSession.prototype = {
|
|||
*/
|
||||
function LayoutView(inspector, win) {
|
||||
this.inspector = inspector;
|
||||
|
||||
this.doc = win.document;
|
||||
this.sizeLabel = this.doc.querySelector(".size > span");
|
||||
this.sizeHeadingLabel = this.doc.getElementById("element-size");
|
||||
this.sizeLabel = this.doc.querySelector(".layout-size > span");
|
||||
this.sizeHeadingLabel = this.doc.getElementById("layout-element-size");
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
@ -158,50 +156,78 @@ LayoutView.prototype = {
|
|||
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
||||
this.inspector.sidebar.on("select", this.onSidebarSelect);
|
||||
|
||||
this.initBoxModelHighlighter();
|
||||
|
||||
// Store for the different dimensions of the node.
|
||||
// 'selector' refers to the element that holds the value in view.xhtml;
|
||||
// 'property' is what we are measuring;
|
||||
// 'value' is the computed dimension, computed in update().
|
||||
this.map = {
|
||||
position: {selector: "#element-position",
|
||||
property: "position",
|
||||
value: undefined},
|
||||
marginTop: {selector: ".margin.top > span",
|
||||
property: "margin-top",
|
||||
value: undefined},
|
||||
marginBottom: {selector: ".margin.bottom > span",
|
||||
property: "margin-bottom",
|
||||
value: undefined},
|
||||
marginLeft: {selector: ".margin.left > span",
|
||||
property: "margin-left",
|
||||
value: undefined},
|
||||
marginRight: {selector: ".margin.right > span",
|
||||
property: "margin-right",
|
||||
value: undefined},
|
||||
paddingTop: {selector: ".padding.top > span",
|
||||
property: "padding-top",
|
||||
value: undefined},
|
||||
paddingBottom: {selector: ".padding.bottom > span",
|
||||
property: "padding-bottom",
|
||||
value: undefined},
|
||||
paddingLeft: {selector: ".padding.left > span",
|
||||
property: "padding-left",
|
||||
value: undefined},
|
||||
paddingRight: {selector: ".padding.right > span",
|
||||
property: "padding-right",
|
||||
value: undefined},
|
||||
borderTop: {selector: ".border.top > span",
|
||||
property: "border-top-width",
|
||||
value: undefined},
|
||||
borderBottom: {selector: ".border.bottom > span",
|
||||
property: "border-bottom-width",
|
||||
value: undefined},
|
||||
borderLeft: {selector: ".border.left > span",
|
||||
property: "border-left-width",
|
||||
value: undefined},
|
||||
borderRight: {selector: ".border.right > span",
|
||||
property: "border-right-width",
|
||||
value: undefined}
|
||||
position: {
|
||||
selector: "#layout-element-position",
|
||||
property: "position",
|
||||
value: undefined
|
||||
},
|
||||
marginTop: {
|
||||
selector: ".layout-margin.layout-top > span",
|
||||
property: "margin-top",
|
||||
value: undefined
|
||||
},
|
||||
marginBottom: {
|
||||
selector: ".layout-margin.layout-bottom > span",
|
||||
property: "margin-bottom",
|
||||
value: undefined
|
||||
},
|
||||
marginLeft: {
|
||||
selector: ".layout-margin.layout-left > span",
|
||||
property: "margin-left",
|
||||
value: undefined
|
||||
},
|
||||
marginRight: {
|
||||
selector: ".layout-margin.layout-right > span",
|
||||
property: "margin-right",
|
||||
value: undefined
|
||||
},
|
||||
paddingTop: {
|
||||
selector: ".layout-padding.layout-top > span",
|
||||
property: "padding-top",
|
||||
value: undefined
|
||||
},
|
||||
paddingBottom: {
|
||||
selector: ".layout-padding.layout-bottom > span",
|
||||
property: "padding-bottom",
|
||||
value: undefined
|
||||
},
|
||||
paddingLeft: {
|
||||
selector: ".layout-padding.layout-left > span",
|
||||
property: "padding-left",
|
||||
value: undefined
|
||||
},
|
||||
paddingRight: {
|
||||
selector: ".layout-padding.layout-right > span",
|
||||
property: "padding-right",
|
||||
value: undefined
|
||||
},
|
||||
borderTop: {
|
||||
selector: ".layout-border.layout-top > span",
|
||||
property: "border-top-width",
|
||||
value: undefined
|
||||
},
|
||||
borderBottom: {
|
||||
selector: ".layout-border.layout-bottom > span",
|
||||
property: "border-bottom-width",
|
||||
value: undefined
|
||||
},
|
||||
borderLeft: {
|
||||
selector: ".layout-border.layout-left > span",
|
||||
property: "border-left-width",
|
||||
value: undefined
|
||||
},
|
||||
borderRight: {
|
||||
selector: ".layout-border.layout-right > span",
|
||||
property: "border-right-width",
|
||||
value: undefined
|
||||
}
|
||||
};
|
||||
|
||||
// Make each element the dimensions editable
|
||||
|
@ -219,6 +245,24 @@ LayoutView.prototype = {
|
|||
}
|
||||
|
||||
this.onNewNode();
|
||||
|
||||
// Mark document as RTL or LTR:
|
||||
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Ci.nsIXULChromeRegistry);
|
||||
let dir = chromeReg.isLocaleRTL("global");
|
||||
let container = this.doc.getElementById("layout-container");
|
||||
container.setAttribute("dir", dir ? "rtl" : "ltr");
|
||||
},
|
||||
|
||||
initBoxModelHighlighter: function() {
|
||||
let highlightElts = this.doc.querySelectorAll("#layout-container *[title]");
|
||||
this.onHighlightMouseOver = this.onHighlightMouseOver.bind(this);
|
||||
this.onHighlightMouseOut = this.onHighlightMouseOut.bind(this);
|
||||
|
||||
for (let element of highlightElts) {
|
||||
element.addEventListener("mouseover", this.onHighlightMouseOver, true);
|
||||
element.addEventListener("mouseout", this.onHighlightMouseOut, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -256,7 +300,7 @@ LayoutView.prototype = {
|
|||
*/
|
||||
initEditor: function(element, event, dimension) {
|
||||
let { property } = dimension;
|
||||
let session = new EditingSession(document, this.elementRules);
|
||||
let session = new EditingSession(this.doc, this.elementRules);
|
||||
let initialValue = session.getProperty(property);
|
||||
|
||||
let editor = new InplaceEditor({
|
||||
|
@ -264,7 +308,7 @@ LayoutView.prototype = {
|
|||
initial: initialValue,
|
||||
|
||||
start: editor => {
|
||||
editor.elt.parentNode.classList.add("editing");
|
||||
editor.elt.parentNode.classList.add("layout-editing");
|
||||
},
|
||||
|
||||
change: value => {
|
||||
|
@ -288,7 +332,7 @@ LayoutView.prototype = {
|
|||
},
|
||||
|
||||
done: (value, commit) => {
|
||||
editor.elt.parentNode.classList.remove("editing");
|
||||
editor.elt.parentNode.classList.remove("layout-editing");
|
||||
if (!commit) {
|
||||
session.revert();
|
||||
session.destroy();
|
||||
|
@ -321,6 +365,13 @@ LayoutView.prototype = {
|
|||
* Destroy the nodes. Remove listeners.
|
||||
*/
|
||||
destroy: function() {
|
||||
let highlightElts = this.doc.querySelectorAll("#layout-container *[title]");
|
||||
|
||||
for (let element of highlightElts) {
|
||||
element.removeEventListener("mouseover", this.onHighlightMouseOver, true);
|
||||
element.removeEventListener("mouseout", this.onHighlightMouseOut, true);
|
||||
}
|
||||
|
||||
this.inspector.sidebar.off("layoutview-selected", this.onNewNode);
|
||||
this.inspector.selection.off("new-node-front", this.onNewSelection);
|
||||
this.inspector.sidebar.off("select", this.onSidebarSelect);
|
||||
|
@ -360,6 +411,23 @@ LayoutView.prototype = {
|
|||
return this.update();
|
||||
},
|
||||
|
||||
onHighlightMouseOver: function(e) {
|
||||
let region = e.target.getAttribute("data-box");
|
||||
if (!region) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.showBoxModel({
|
||||
region,
|
||||
showOnly: region,
|
||||
onlyRegionArea: true
|
||||
});
|
||||
},
|
||||
|
||||
onHighlightMouseOut: function() {
|
||||
this.hideBoxModel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Stop tracking reflows and hide all values when no node is selected or the
|
||||
* layout-view is hidden, otherwise track reflows and show values.
|
||||
|
@ -371,7 +439,9 @@ LayoutView.prototype = {
|
|||
}
|
||||
this.isActive = isActive;
|
||||
|
||||
this.doc.body.classList.toggle("inactive", !isActive);
|
||||
let panel = this.doc.getElementById("sidebar-panel-layoutview");
|
||||
panel.classList.toggle("inactive", !isActive);
|
||||
|
||||
if (isActive) {
|
||||
this.trackReflows();
|
||||
} else {
|
||||
|
@ -536,64 +606,12 @@ LayoutView.prototype = {
|
|||
manageOverflowingText: function(span) {
|
||||
let classList = span.parentNode.classList;
|
||||
|
||||
if (classList.contains("left") || classList.contains("right")) {
|
||||
if (classList.contains("layout-left") ||
|
||||
classList.contains("layout-right")) {
|
||||
let force = span.textContent.length > LONG_TEXT_ROTATE_LIMIT;
|
||||
classList.toggle("rotate", force);
|
||||
classList.toggle("layout-rotate", force);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var elts;
|
||||
|
||||
var onmouseover = function(e) {
|
||||
let region = e.target.getAttribute("data-box");
|
||||
if (!region) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.layoutview.showBoxModel({
|
||||
region,
|
||||
showOnly: region,
|
||||
onlyRegionArea: true
|
||||
});
|
||||
|
||||
return false;
|
||||
}.bind(window);
|
||||
|
||||
var onmouseout = function() {
|
||||
this.layoutview.hideBoxModel();
|
||||
return false;
|
||||
}.bind(window);
|
||||
|
||||
window.setPanel = function(panel) {
|
||||
this.layoutview = new LayoutView(panel, window);
|
||||
|
||||
// Box model highlighter mechanism
|
||||
elts = document.querySelectorAll("*[title]");
|
||||
for (let i = 0; i < elts.length; i++) {
|
||||
let elt = elts[i];
|
||||
elt.addEventListener("mouseover", onmouseover, true);
|
||||
elt.addEventListener("mouseout", onmouseout, true);
|
||||
}
|
||||
|
||||
// Mark document as RTL or LTR:
|
||||
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Ci.nsIXULChromeRegistry);
|
||||
let dir = chromeReg.isLocaleRTL("global");
|
||||
document.body.setAttribute("dir", dir ? "rtl" : "ltr");
|
||||
|
||||
window.parent.postMessage("layoutview-ready", "*");
|
||||
};
|
||||
|
||||
window.onunload = function() {
|
||||
if (this.layoutview) {
|
||||
this.layoutview.destroy();
|
||||
}
|
||||
if (elts) {
|
||||
for (let i = 0; i < elts.length; i++) {
|
||||
let elt = elts[i];
|
||||
elt.removeEventListener("mouseover", onmouseover, true);
|
||||
elt.removeEventListener("mouseout", onmouseout, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.LayoutView = LayoutView;
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % layoutviewDTD SYSTEM "chrome://devtools/locale/layoutview.dtd" >
|
||||
%layoutviewDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<head>
|
||||
<title>&layoutViewTitle;</title>
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
|
||||
<script type="application/javascript;version=1.8" src="layout.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/layout.css" type="text/css"/>
|
||||
|
||||
</head>
|
||||
<body class="theme-sidebar devtools-monospace">
|
||||
|
||||
<p id="header">
|
||||
<span id="element-size"></span><span id="element-position"></span>
|
||||
</p>
|
||||
|
||||
<div id="main">
|
||||
|
||||
<span class="legend" data-box="margin" title="&margin.tooltip;">&margin.tooltip;</span>
|
||||
<div id="margins" data-box="margin" title="&margin.tooltip;">
|
||||
<span class="legend" data-box="border" title="&border.tooltip;">&border.tooltip;</span>
|
||||
<div id="borders" data-box="border" title="&border.tooltip;">
|
||||
<span class="legend" data-box="padding" title="&padding.tooltip;">&padding.tooltip;</span>
|
||||
<div id="padding" data-box="padding" title="&padding.tooltip;">
|
||||
<div id="content" data-box="content" title="&content.tooltip;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="border top"><span data-box="border" class="editable" title="border-top"></span></p>
|
||||
<p class="border right"><span data-box="border" class="editable" title="border-right"></span></p>
|
||||
<p class="border bottom"><span data-box="border" class="editable" title="border-bottom"></span></p>
|
||||
<p class="border left"><span data-box="border" class="editable" title="border-left"></span></p>
|
||||
|
||||
<p class="margin top"><span data-box="margin" class="editable" title="margin-top"></span></p>
|
||||
<p class="margin right"><span data-box="margin" class="editable" title="margin-right"></span></p>
|
||||
<p class="margin bottom"><span data-box="margin" class="editable" title="margin-bottom"></span></p>
|
||||
<p class="margin left"><span data-box="margin" class="editable" title="margin-left"></span></p>
|
||||
|
||||
<p class="padding top"><span data-box="padding" class="editable" title="padding-top"></span></p>
|
||||
<p class="padding right"><span data-box="padding" class="editable" title="padding-right"></span></p>
|
||||
<p class="padding bottom"><span data-box="padding" class="editable" title="padding-bottom"></span></p>
|
||||
<p class="padding left"><span data-box="padding" class="editable" title="padding-left"></span></p>
|
||||
|
||||
<p class="size"><span data-box="content" title="&content.tooltip;"></span></p>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="display: none">
|
||||
<p id="dummy"></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -9,42 +9,126 @@
|
|||
|
||||
// Expected values:
|
||||
var res1 = [
|
||||
{selector: "#element-size", value: "160" + "\u00D7" + "160.117"},
|
||||
{selector: ".size > span", value: "100" + "\u00D7" + "100.117"},
|
||||
{selector: ".margin.top > span", value: 30},
|
||||
{selector: ".margin.left > span", value: "auto"},
|
||||
{selector: ".margin.bottom > span", value: 30},
|
||||
{selector: ".margin.right > span", value: "auto"},
|
||||
{selector: ".padding.top > span", value: 20},
|
||||
{selector: ".padding.left > span", value: 20},
|
||||
{selector: ".padding.bottom > span", value: 20},
|
||||
{selector: ".padding.right > span", value: 20},
|
||||
{selector: ".border.top > span", value: 10},
|
||||
{selector: ".border.left > span", value: 10},
|
||||
{selector: ".border.bottom > span", value: 10},
|
||||
{selector: ".border.right > span", value: 10},
|
||||
{
|
||||
selector: "#layout-element-size",
|
||||
value: "160" + "\u00D7" + "160.117"
|
||||
},
|
||||
{
|
||||
selector: ".layout-size > span",
|
||||
value: "100" + "\u00D7" + "100.117"
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-top > span",
|
||||
value: 30
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-left > span",
|
||||
value: "auto"
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-bottom > span",
|
||||
value: 30
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-right > span",
|
||||
value: "auto"
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-top > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-left > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-bottom > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-right > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-top > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-left > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-bottom > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-right > span",
|
||||
value: 10
|
||||
},
|
||||
];
|
||||
|
||||
var res2 = [
|
||||
{selector: "#element-size", value: "190" + "\u00D7" + "210"},
|
||||
{selector: ".size > span", value: "100" + "\u00D7" + "150"},
|
||||
{selector: ".margin.top > span", value: 30},
|
||||
{selector: ".margin.left > span", value: "auto"},
|
||||
{selector: ".margin.bottom > span", value: 30},
|
||||
{selector: ".margin.right > span", value: "auto"},
|
||||
{selector: ".padding.top > span", value: 20},
|
||||
{selector: ".padding.left > span", value: 20},
|
||||
{selector: ".padding.bottom > span", value: 20},
|
||||
{selector: ".padding.right > span", value: 50},
|
||||
{selector: ".border.top > span", value: 10},
|
||||
{selector: ".border.left > span", value: 10},
|
||||
{selector: ".border.bottom > span", value: 10},
|
||||
{selector: ".border.right > span", value: 10},
|
||||
{
|
||||
selector: "#layout-element-size",
|
||||
value: "190" + "\u00D7" + "210"
|
||||
},
|
||||
{
|
||||
selector: ".layout-size > span",
|
||||
value: "100" + "\u00D7" + "150"
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-top > span",
|
||||
value: 30
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-left > span",
|
||||
value: "auto"
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-bottom > span",
|
||||
value: 30
|
||||
},
|
||||
{
|
||||
selector: ".layout-margin.layout-right > span",
|
||||
value: "auto"
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-top > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-left > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-bottom > span",
|
||||
value: 20
|
||||
},
|
||||
{
|
||||
selector: ".layout-padding.layout-right > span",
|
||||
value: 50
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-top > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-left > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-bottom > span",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
selector: ".layout-border.layout-right > span",
|
||||
value: 10
|
||||
},
|
||||
];
|
||||
|
||||
add_task(function*() {
|
||||
let style = "div { position: absolute; top: 42px; left: 42px; height: 100.111px; width: 100px; border: 10px solid black; padding: 20px; margin: 30px auto;}";
|
||||
let html = "<style>" + style + "</style><div></div>"
|
||||
let html = "<style>" + style + "</style><div></div>";
|
||||
|
||||
yield addTab("data:text/html," + encodeURIComponent(html));
|
||||
let {toolbox, inspector, view} = yield openLayoutView();
|
||||
|
|
|
@ -34,7 +34,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "margin-top"), "", "Should be no margin-top on the element.")
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".margin.top > span");
|
||||
let span = view.doc.querySelector(".layout-margin.layout-top > span");
|
||||
is(span.textContent, 5, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -60,7 +60,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "margin-left"), "", "Should be no margin-top on the element.")
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".margin.left > span");
|
||||
let span = view.doc.querySelector(".layout-margin.layout-left > span");
|
||||
is(span.textContent, 10, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -97,7 +97,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "margin-left"), "20px", "Should be the right margin-top on the element.")
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".margin.left > span");
|
||||
let span = view.doc.querySelector(".layout-margin.layout-left > span");
|
||||
is(span.textContent, 20, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -127,7 +127,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".margin.right > span");
|
||||
let span = view.doc.querySelector(".layout-margin.layout-right > span");
|
||||
is(span.textContent, 15, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -153,7 +153,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div4", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".margin.top > span");
|
||||
let span = view.doc.querySelector(".layout-margin.layout-top > span");
|
||||
is(span.textContent, 1, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
|
|
@ -34,7 +34,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.bottom > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-bottom > span");
|
||||
is(span.textContent, 5, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -63,7 +63,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.left > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-left > span");
|
||||
is(span.textContent, 5, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -92,7 +92,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.left > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-left > span");
|
||||
is(span.textContent, 5, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -121,7 +121,7 @@ function*(inspector, view) {
|
|||
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.left > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-left > span");
|
||||
is(span.textContent, 5, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
|
|
@ -27,7 +27,7 @@ add_task(function*() {
|
|||
is(getStyle(node, "border-top-style"), "", "Should have the right border");
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".border.top > span");
|
||||
let span = view.doc.querySelector(".layout-border.layout-top > span");
|
||||
is(span.textContent, 0, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
|
|
@ -32,7 +32,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "padding-top"), "", "Should have the right padding");
|
||||
yield selectNode("#div1", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.top > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-top > span");
|
||||
is(span.textContent, 3, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -65,7 +65,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "border-bottom-width"), "", "Should have the right border-bottom-width");
|
||||
yield selectNode("#div2", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".border.bottom > span");
|
||||
let span = view.doc.querySelector(".layout-border.layout-bottom > span");
|
||||
is(span.textContent, 16, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
@ -91,7 +91,7 @@ function*(inspector, view) {
|
|||
is(getStyle(node, "padding-right"), "", "Should have the right padding");
|
||||
yield selectNode("#div3", inspector);
|
||||
|
||||
let span = view.doc.querySelector(".padding.right > span");
|
||||
let span = view.doc.querySelector(".layout-padding.layout-right > span");
|
||||
is(span.textContent, 32, "Should have the right value in the box model.");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(span, {}, view.doc.defaultView);
|
||||
|
|
|
@ -27,16 +27,16 @@ add_task(function*() {
|
|||
highlighterOptions = options;
|
||||
}
|
||||
|
||||
let elt = view.doc.getElementById("margins");
|
||||
let elt = view.doc.getElementById("layout-margins");
|
||||
yield testGuideOnLayoutHover(elt, "margin", inspector, view);
|
||||
|
||||
elt = view.doc.getElementById("borders");
|
||||
elt = view.doc.getElementById("layout-borders");
|
||||
yield testGuideOnLayoutHover(elt, "border", inspector, view);
|
||||
|
||||
elt = view.doc.getElementById("padding");
|
||||
elt = view.doc.getElementById("layout-padding");
|
||||
yield testGuideOnLayoutHover(elt, "padding", inspector, view);
|
||||
|
||||
elt = view.doc.getElementById("content");
|
||||
elt = view.doc.getElementById("layout-content");
|
||||
yield testGuideOnLayoutHover(elt, "content", inspector, view);
|
||||
});
|
||||
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
// Test that longer values are rotated on the side
|
||||
|
||||
const res1 = [
|
||||
{selector: ".margin.top > span", value: 30},
|
||||
{selector: ".margin.left > span", value: "auto"},
|
||||
{selector: ".margin.bottom > span", value: 30},
|
||||
{selector: ".margin.right > span", value: "auto"},
|
||||
{selector: ".padding.top > span", value: 20},
|
||||
{selector: ".padding.left > span", value: 2000000},
|
||||
{selector: ".padding.bottom > span", value: 20},
|
||||
{selector: ".padding.right > span", value: 20},
|
||||
{selector: ".border.top > span", value: 10},
|
||||
{selector: ".border.left > span", value: 10},
|
||||
{selector: ".border.bottom > span", value: 10},
|
||||
{selector: ".border.right > span", value: 10},
|
||||
{selector: ".layout-margin.layout-top > span", value: 30},
|
||||
{selector: ".layout-margin.layout-left > span", value: "auto"},
|
||||
{selector: ".layout-margin.layout-bottom > span", value: 30},
|
||||
{selector: ".layout-margin.layout-right > span", value: "auto"},
|
||||
{selector: ".layout-padding.layout-top > span", value: 20},
|
||||
{selector: ".layout-padding.layout-left > span", value: 2000000},
|
||||
{selector: ".layout-padding.layout-bottom > span", value: 20},
|
||||
{selector: ".layout-padding.layout-right > span", value: 20},
|
||||
{selector: ".layout-border.layout-top > span", value: 10},
|
||||
{selector: ".layout-border.layout-left > span", value: 10},
|
||||
{selector: ".layout-border.layout-bottom > span", value: 10},
|
||||
{selector: ".layout-border.layout-right > span", value: 10},
|
||||
];
|
||||
|
||||
const TEST_URI = encodeURIComponent([
|
||||
|
@ -37,10 +37,12 @@ add_task(function*() {
|
|||
for (let i = 0; i < res1.length; i++) {
|
||||
let elt = view.doc.querySelector(res1[i].selector);
|
||||
let isLong = elt.textContent.length > LONG_TEXT_ROTATE_LIMIT;
|
||||
let classList = elt.parentNode.classList
|
||||
let canBeRotated = classList.contains("left") || classList.contains("right");
|
||||
let isRotated = classList.contains("rotate");
|
||||
let classList = elt.parentNode.classList;
|
||||
let canBeRotated = classList.contains("layout-left") ||
|
||||
classList.contains("layout-right");
|
||||
let isRotated = classList.contains("layout-rotate");
|
||||
|
||||
is(canBeRotated && isLong, isRotated, res1[i].selector + " correctly rotated.");
|
||||
is(canBeRotated && isLong,
|
||||
isRotated, res1[i].selector + " correctly rotated.");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -76,24 +76,24 @@ add_task(function*() {
|
|||
|
||||
info("Checking the regions tooltips");
|
||||
|
||||
ok(view.doc.querySelector("#margins").hasAttribute("title"),
|
||||
ok(view.doc.querySelector("#layout-margins").hasAttribute("title"),
|
||||
"The margin region has a tooltip");
|
||||
is(view.doc.querySelector("#margins").getAttribute("title"), "margin",
|
||||
is(view.doc.querySelector("#layout-margins").getAttribute("title"), "margin",
|
||||
"The margin region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#borders").hasAttribute("title"),
|
||||
ok(view.doc.querySelector("#layout-borders").hasAttribute("title"),
|
||||
"The border region has a tooltip");
|
||||
is(view.doc.querySelector("#borders").getAttribute("title"), "border",
|
||||
is(view.doc.querySelector("#layout-borders").getAttribute("title"), "border",
|
||||
"The border region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#padding").hasAttribute("title"),
|
||||
ok(view.doc.querySelector("#layout-padding").hasAttribute("title"),
|
||||
"The padding region has a tooltip");
|
||||
is(view.doc.querySelector("#padding").getAttribute("title"), "padding",
|
||||
is(view.doc.querySelector("#layout-padding").getAttribute("title"), "padding",
|
||||
"The padding region has the correct tooltip content");
|
||||
|
||||
ok(view.doc.querySelector("#content").hasAttribute("title"),
|
||||
ok(view.doc.querySelector("#layout-content").hasAttribute("title"),
|
||||
"The content region has a tooltip");
|
||||
is(view.doc.querySelector("#content").getAttribute("title"), "content",
|
||||
is(view.doc.querySelector("#layout-content").getAttribute("title"), "content",
|
||||
"The content region has the correct tooltip content");
|
||||
|
||||
for (let {selector, values} of VALUES_TEST_DATA) {
|
||||
|
|
|
@ -19,7 +19,7 @@ function*(inspector, view) {
|
|||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
let paddingElt = view.doc.querySelector(".layout-padding.layout-top > span");
|
||||
is(paddingElt.textContent, "50");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
|
@ -44,7 +44,7 @@ function*(inspector, view) {
|
|||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
let sizeElt = view.doc.querySelector(".layout-size > span");
|
||||
is(sizeElt.textContent, "100" + "\u00D7" + "100");
|
||||
|
||||
info("Listening for layout-view changes and modifying the size");
|
||||
|
@ -70,7 +70,7 @@ function*(inspector, view) {
|
|||
|
||||
info("Checking that the layout-view shows the right value, which is the" +
|
||||
"modified value from step one because of the bfcache");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
let paddingElt = view.doc.querySelector(".layout-padding.layout-top > span");
|
||||
is(paddingElt.textContent, "20");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
|
|
|
@ -26,7 +26,7 @@ function* assertLayoutView(inspector, view) {
|
|||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
let paddingElt = view.doc.querySelector(".layout-padding.layout-top > span");
|
||||
is(paddingElt.textContent, "50");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
|
|
|
@ -22,7 +22,7 @@ function*(inspector, view, iframe2) {
|
|||
yield selectNodeInIframe2("div", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
let sizeElt = view.doc.querySelector(".layout-size > span");
|
||||
is(sizeElt.textContent, "400\u00D7200");
|
||||
|
||||
info("Listening for layout-view changes and modifying its size");
|
||||
|
@ -46,7 +46,7 @@ function*(inspector, view, iframe2) {
|
|||
yield selectNodeInIframe1("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
let sizeElt = view.doc.querySelector(".layout-size > span");
|
||||
is(sizeElt.textContent, "100\u00D7100");
|
||||
|
||||
info("Listening for layout-view changes and modifying its size");
|
||||
|
|
|
@ -52,7 +52,7 @@ function selectAndHighlightNode(nodeOrSelector, inspector) {
|
|||
* view is visible and ready
|
||||
*/
|
||||
function openLayoutView() {
|
||||
return openInspectorSidebarTab("layoutview").then(objects => {
|
||||
return openInspectorSidebarTab("layoutview").then(({toolbox, inspector}) => {
|
||||
// The actual highligher show/hide methods are mocked in layoutview tests.
|
||||
// The highlighter is tested in devtools/inspector/test.
|
||||
function mockHighlighter({highlighter}) {
|
||||
|
@ -63,9 +63,13 @@ function openLayoutView() {
|
|||
return promise.resolve();
|
||||
};
|
||||
}
|
||||
mockHighlighter(objects.toolbox);
|
||||
mockHighlighter(toolbox);
|
||||
|
||||
return objects;
|
||||
return {
|
||||
toolbox,
|
||||
inspector,
|
||||
view: inspector.layoutview
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
:root {
|
||||
-moz-control-character-visibility: visible;
|
||||
}
|
||||
|
||||
body {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
/* Force height and width (possibly overflowing) from inline elements.
|
||||
* This allows long overflows of text or input fields to still be styled with
|
||||
* the container, rather than the background disappearing when scrolling */
|
||||
#root {
|
||||
float: left;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
body.dragging .tag-line {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
#root-wrapper:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.html-editor {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
|
||||
/* Use the same margin/padding trick used by .child tags to ensure that
|
||||
* the editor covers up any content to the left (including expander arrows
|
||||
* and hover effects). */
|
||||
margin-left: -1000em;
|
||||
padding-left: 1000em;
|
||||
}
|
||||
|
||||
.html-editor-inner {
|
||||
border: solid .1px;
|
||||
flex: 1 1 auto;
|
||||
|
||||
/* Keep the editor away from the markup view floating scrollbars */
|
||||
-moz-margin-end: 12px;
|
||||
}
|
||||
|
||||
.html-editor iframe {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.children {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Tags are organized in a UL/LI tree and indented thanks to a left padding.
|
||||
* A very large padding is used in combination with a slightly smaller margin
|
||||
* to make sure childs actually span from edge-to-edge. */
|
||||
.child {
|
||||
margin-left: -1000em;
|
||||
padding-left: 1001em;
|
||||
}
|
||||
|
||||
/* Normally this element takes space in the layout even if it's position: relative
|
||||
* by adding height: 0 we let surrounding elements to fill the blank space */
|
||||
.child.dragging {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
opacity: 0.7;
|
||||
z-index: 1;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* Indicates a tag-line in the markup-view as being an active drop target by
|
||||
* drawing a horizontal line where the dragged element would be inserted if
|
||||
* dropped here */
|
||||
.tag-line.drop-target::before,
|
||||
.tag-line.drag-target::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
/* Offset these by 1000px to make sure they cover the full width of the view */
|
||||
padding-left: 1000px;
|
||||
left: -1000px;
|
||||
}
|
||||
|
||||
.tag-line.drag-target::before {
|
||||
border-top: 2px solid var(--theme-content-color2);
|
||||
}
|
||||
|
||||
.tag-line.drop-target::before {
|
||||
border-top: 2px solid var(--theme-contrast-background);
|
||||
}
|
||||
|
||||
/* In case the indicator is put on the closing .tag-line, the indentation level
|
||||
* will become misleading, so we push it forward to match the indentation level */
|
||||
ul.children + .tag-line::before {
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.tag-line {
|
||||
min-height: 1.4em;
|
||||
line-height: 1.4em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.html-editor-container {
|
||||
position: relative;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
/* This extra element placed in each tag is positioned absolutely to cover the
|
||||
* whole tag line and is used for background styling (when a selection is made
|
||||
* or when the tag is flashing) */
|
||||
.tag-line .tag-state {
|
||||
position: absolute;
|
||||
left: -1000em;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.expander {
|
||||
display: inline-block;
|
||||
margin-left: -14px;
|
||||
vertical-align: middle;
|
||||
/* Make sure the expander still appears above the tag-state */
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.child.collapsed .child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.child > .tag-line:first-child .close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.child.collapsed > .tag-line:first-child .close {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.child.collapsed > .tag-line ~ .tag-line {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.child.collapsed .close {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.closing-bracket {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.newattr {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1ex;
|
||||
margin-right: -1em;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
.attr-value .link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.newattr:focus {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.flash-out {
|
||||
transition: background .5s;
|
||||
}
|
||||
|
||||
.tag-line {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.markupview-events {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.editor {
|
||||
/* Make sure the editor still appears above the tag-state */
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.editor.text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.editor.text pre,
|
||||
.editor.comment pre {
|
||||
font: inherit;
|
||||
}
|
|
@ -76,14 +76,23 @@ add_task(function*() {
|
|||
EventUtils.sendKey("return", inspector.panelWin);
|
||||
let editor = inplaceEditor(attr);
|
||||
|
||||
for (let i = 0; i < TEST_DATA.length; i ++) {
|
||||
for (let i = 0; i < TEST_DATA.length; i++) {
|
||||
// Expect a markupmutation event at the last iteration since that's when the
|
||||
// attribute is actually created.
|
||||
let onMutation = i === TEST_DATA.length - 1
|
||||
? inspector.once("markupmutation") : null;
|
||||
yield enterData(i, editor, inspector);
|
||||
yield checkData(i, editor, inspector);
|
||||
yield onMutation;
|
||||
}
|
||||
|
||||
// Undoing the action will remove the new attribute, so make sure to wait for
|
||||
// the markupmutation event here again.
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
while (inspector.markup.undo.canUndo()) {
|
||||
yield undoChange(inspector);
|
||||
}
|
||||
yield onMutation;
|
||||
});
|
||||
|
||||
function enterData(index, editor, inspector) {
|
||||
|
|
|
@ -13,6 +13,7 @@ add_task(function*() {
|
|||
let {markup} = inspector;
|
||||
|
||||
info("Get a test container");
|
||||
yield selectNode("#test", inspector);
|
||||
let container = yield getContainerForSelector("#test", inspector);
|
||||
|
||||
info("Simulate a drag/drop on this container");
|
||||
|
|
|
@ -18,10 +18,11 @@ add_task(function*() {
|
|||
yield inspector.markup.expandNode(parentFront);
|
||||
yield waitForMultipleChildrenUpdates(inspector);
|
||||
|
||||
info("Getting the ::before pseudo element");
|
||||
info("Getting the ::before pseudo element and selecting it");
|
||||
let parentContainer = yield getContainerForNodeFront(parentFront, inspector);
|
||||
let beforePseudo = parentContainer.elt.children[1].firstChild.container;
|
||||
parentContainer.elt.scrollIntoView(true);
|
||||
yield selectNode(beforePseudo.node, inspector);
|
||||
|
||||
info("Simulate dragging the ::before pseudo element");
|
||||
yield simulateNodeDrag(inspector, beforePseudo);
|
||||
|
@ -33,10 +34,11 @@ add_task(function*() {
|
|||
yield inspector.markup.expandNode(inputFront);
|
||||
yield waitForMultipleChildrenUpdates(inspector);
|
||||
|
||||
info("Getting the anonymous node");
|
||||
info("Getting the anonymous node and selecting it");
|
||||
let inputContainer = yield getContainerForNodeFront(inputFront, inspector);
|
||||
let anonymousDiv = inputContainer.elt.children[1].firstChild.container;
|
||||
inputContainer.elt.scrollIntoView(true);
|
||||
yield selectNode(anonymousDiv.node, inspector);
|
||||
|
||||
info("Simulate dragging the anonymous node");
|
||||
yield simulateNodeDrag(inspector, anonymousDiv);
|
||||
|
|
|
@ -48,27 +48,24 @@ function selectPreviousNodeWithArrowUp(inspector) {
|
|||
}
|
||||
|
||||
function* selectWithBrowserMenu(inspector) {
|
||||
let contentAreaContextMenu = document.querySelector("#contentAreaContextMenu");
|
||||
let contextOpened = once(contentAreaContextMenu, "popupshown");
|
||||
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("div", {
|
||||
type: "contextmenu",
|
||||
button: 2
|
||||
}, gBrowser.selectedBrowser);
|
||||
|
||||
// nsContextMenu also requires the popupNode to be set, but we can't set it to
|
||||
// node under e10s as it's a CPOW, not a DOM node. But under e10s,
|
||||
// nsContextMenu won't use the property anyway, so just try/catching is ok.
|
||||
try {
|
||||
document.popupNode = getNode("div");
|
||||
} catch (e) {}
|
||||
yield contextOpened;
|
||||
|
||||
let contentAreaContextMenu = document.querySelector("#contentAreaContextMenu");
|
||||
let contextMenu = new nsContextMenu(contentAreaContextMenu);
|
||||
yield contextMenu.inspectNode();
|
||||
yield gContextMenu.inspectNode();
|
||||
|
||||
let contextClosed = once(contentAreaContextMenu, "popuphidden");
|
||||
contentAreaContextMenu.hidden = true;
|
||||
contentAreaContextMenu.hidePopup();
|
||||
contextMenu.hiding();
|
||||
|
||||
yield inspector.once("inspector-updated");
|
||||
yield contextClosed;
|
||||
}
|
||||
|
||||
function* selectWithElementPicker(inspector, testActor) {
|
||||
|
|
|
@ -24,7 +24,7 @@ const TEST_DATA = [
|
|||
["down", "node5"],
|
||||
["down", "node6"],
|
||||
["down", "*comment*"],
|
||||
["down" , "node7"],
|
||||
["down", "node7"],
|
||||
["right", "node7"],
|
||||
["down", "*text*"],
|
||||
["down", "node8"],
|
||||
|
@ -83,10 +83,17 @@ add_task(function*() {
|
|||
info("Checking the right node is selected");
|
||||
checkSelectedNode(key, className, inspector);
|
||||
}
|
||||
|
||||
// In theory, we should wait for the inspector-updated event at each iteration
|
||||
// of the previous loop where we expect the current node to change (because
|
||||
// changing the current node ends up refreshing the rule-view, breadcrumbs,
|
||||
// ...), but this would make this test a *lot* slower. Instead, having a final
|
||||
// catch-all event works too.
|
||||
yield inspector.once("inspector-updated");
|
||||
});
|
||||
|
||||
function pressKey(key) {
|
||||
switch(key) {
|
||||
switch (key) {
|
||||
case "right":
|
||||
EventUtils.synthesizeKey("VK_RIGHT", {});
|
||||
break;
|
||||
|
@ -115,12 +122,16 @@ function checkSelectedNode(key, className, inspector) {
|
|||
let node = inspector.selection.nodeFront;
|
||||
|
||||
if (className == "*comment*") {
|
||||
is(node.nodeType, Node.COMMENT_NODE, "Found a comment after pressing " + key);
|
||||
is(node.nodeType, Node.COMMENT_NODE,
|
||||
"Found a comment after pressing " + key);
|
||||
} else if (className == "*text*") {
|
||||
is(node.nodeType, Node.TEXT_NODE, "Found text after pressing " + key);
|
||||
is(node.nodeType, Node.TEXT_NODE,
|
||||
"Found text after pressing " + key);
|
||||
} else if (className == "*doctype*") {
|
||||
is(node.nodeType, Node.DOCUMENT_TYPE_NODE, "Found the doctype after pressing " + key);
|
||||
is(node.nodeType, Node.DOCUMENT_TYPE_NODE,
|
||||
"Found the doctype after pressing " + key);
|
||||
} else {
|
||||
is(node.className, className, "Found node: " + className + " after pressing " + key);
|
||||
is(node.className, className,
|
||||
"Found node: " + className + " after pressing " + key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ function CssRuleView(inspector, document, store, pageStyle) {
|
|||
autoSelect: true,
|
||||
theme: "auto"
|
||||
};
|
||||
this.popup = new AutocompletePopup(this.styleWindow.parent.document, options);
|
||||
this.popup = new AutocompletePopup(this.styleDocument, options);
|
||||
|
||||
this._showEmpty();
|
||||
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % inspectorDTD SYSTEM "chrome://devtools/locale/styleinspector.dtd">
|
||||
%inspectorDTD;
|
||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||
%globalDTD;
|
||||
]>
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
class="theme-sidebar">
|
||||
<head>
|
||||
<title>&ruleViewTitle;</title>
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/rules.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<script type="application/javascript;version=1.8">
|
||||
window.setPanel = function(panel, iframe) {
|
||||
let {require} = Components.utils.import("resource://devtools/shared/Loader.jsm", {});
|
||||
let {RuleViewTool} = require("devtools/client/inspector/rules/rules");
|
||||
this.ruleview = new RuleViewTool(panel, window);
|
||||
}
|
||||
window.onunload = function() {
|
||||
if (this.ruleview) {
|
||||
this.ruleview.destroy();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body dir="&locale.dir;">
|
||||
<div id="root" class="devtools-monospace">
|
||||
<div id="ruleview-toolbar" class="devtools-toolbar">
|
||||
<div class="devtools-searchbox">
|
||||
<input id="ruleview-searchbox"
|
||||
class="devtools-searchinput devtools-rule-searchbox"
|
||||
type="search" placeholder="&filterStylesPlaceholder;"/>
|
||||
<button id="ruleview-searchinput-clear" class="devtools-searchinput-clear"></button>
|
||||
</div>
|
||||
<button id="ruleview-add-rule-button" title="&addRuleButtonTooltip;" class="devtools-button"></button>
|
||||
<button id="pseudo-class-panel-toggle" title="&togglePseudoClassPanel;" class="devtools-button"></button>
|
||||
</div>
|
||||
<div id="pseudo-class-panel" class="devtools-toolbar" hidden="true" tabindex="-1">
|
||||
<label><input id="pseudo-hover-toggle" type="checkbox" value=":hover" tabindex="-1" />:hover</label>
|
||||
<label><input id="pseudo-active-toggle" type="checkbox" value=":active" tabindex="-1" />:active</label>
|
||||
<label><input id="pseudo-focus-toggle" type="checkbox" value=":focus" tabindex="-1" />:focus</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ruleview-container" class="devtools-monospace">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -43,6 +43,6 @@ function* testCancelNew(view) {
|
|||
"Should have cancelled creating a new text property.");
|
||||
ok(!elementRuleEditor.propertyList.hasChildNodes(),
|
||||
"Should not have any properties.");
|
||||
is(view.styleDocument.body, view.styleDocument.activeElement,
|
||||
is(view.styleDocument.activeElement, view.styleDocument.documentElement,
|
||||
"Correct element has focus");
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ add_task(function*() {
|
|||
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
|
||||
yield onRuleViewChanged;
|
||||
|
||||
is(view.styleDocument.body, view.styleDocument.activeElement,
|
||||
is(view.styleDocument.documentElement, view.styleDocument.activeElement,
|
||||
"Correct element has focus");
|
||||
|
||||
is(elementRuleEditor.rule.textProps.length, 1,
|
||||
|
|
|
@ -48,6 +48,6 @@ function* testCancelNewOnEscape(inspector, view) {
|
|||
"Should have canceled creating a new text property.");
|
||||
ok(!elementRuleEditor.propertyList.hasChildNodes(),
|
||||
"Should not have any properties.");
|
||||
is(view.styleDocument.body, view.styleDocument.activeElement,
|
||||
is(view.styleDocument.documentElement, view.styleDocument.activeElement,
|
||||
"Correct element has focus");
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ add_task(function* () {
|
|||
swatch.click();
|
||||
yield onShown;
|
||||
|
||||
let testNode = yield getNode("#testid");
|
||||
let testNode = getNode("#testid");
|
||||
|
||||
yield simulateColorPickerChange(view, cPicker, [0, 255, 0, 1], {
|
||||
element: testNode,
|
||||
|
|
|
@ -46,7 +46,7 @@ function* basicTest(view, name, result) {
|
|||
swatch.click();
|
||||
yield onShown;
|
||||
|
||||
let testNode = yield getNode("#testid");
|
||||
let testNode = getNode("#testid");
|
||||
|
||||
yield simulateColorPickerChange(view, cPicker, [0, 255, 0, 1], {
|
||||
element: testNode,
|
||||
|
|
|
@ -44,7 +44,7 @@ add_task(function*() {
|
|||
let inspector = toolbox.getPanel("inspector");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
let view = inspector.sidebar.getWindowForTab("ruleview")["ruleview"].view;
|
||||
let view = inspector.ruleview.view;
|
||||
|
||||
checkRuleViewContent(view);
|
||||
});
|
||||
|
|
|
@ -17,15 +17,15 @@ const TEST_URI = `
|
|||
|
||||
add_task(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let {inspector, view} = yield openRuleView();
|
||||
let {view} = yield openRuleView();
|
||||
let container = getRuleViewProperty(view, "body", "color").valueSpan;
|
||||
checkColorCycling(container, inspector);
|
||||
checkColorCycling(container, view);
|
||||
});
|
||||
|
||||
function checkColorCycling(container, inspector) {
|
||||
function checkColorCycling(container, view) {
|
||||
let swatch = container.querySelector(".ruleview-colorswatch");
|
||||
let valueNode = container.querySelector(".ruleview-color");
|
||||
let win = inspector.sidebar.getWindowForTab("ruleview");
|
||||
let win = view.styleWindow;
|
||||
|
||||
// Hex
|
||||
is(valueNode.textContent, "#f00", "Color displayed as a hex value.");
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
add_task(function*() {
|
||||
yield addTab("data:text/html;charset=utf-8,sample document for bug 722691");
|
||||
createDocument();
|
||||
let {toolbox, inspector, view} = yield openRuleView();
|
||||
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("#test", inspector);
|
||||
|
||||
yield testMarginIncrements(view);
|
||||
|
@ -23,16 +23,16 @@ add_task(function*() {
|
|||
});
|
||||
|
||||
function createDocument() {
|
||||
content.document.body.innerHTML = '' +
|
||||
'<style>' +
|
||||
' #test {' +
|
||||
' margin-top:0px;' +
|
||||
' padding-top: 0px;' +
|
||||
' color:#000000;' +
|
||||
' background-color: #000000;' +
|
||||
' }' +
|
||||
'</style>' +
|
||||
'<div id="test"></div>';
|
||||
content.document.body.innerHTML = "" +
|
||||
"<style>" +
|
||||
" #test {" +
|
||||
" margin-top:0px;" +
|
||||
" padding-top: 0px;" +
|
||||
" color:#000000;" +
|
||||
" background-color: #000000;" +
|
||||
" }" +
|
||||
"</style>" +
|
||||
"<div id=\"test\"></div>";
|
||||
}
|
||||
|
||||
function* testMarginIncrements(view) {
|
||||
|
@ -64,13 +64,13 @@ function* testVariousUnitIncrements(view) {
|
|||
2: {start: "0pt", end: "1pt", selectAll: true},
|
||||
3: {start: "0pc", end: "1pc", selectAll: true},
|
||||
4: {start: "0em", end: "1em", selectAll: true},
|
||||
5: {start: "0%", end: "1%", selectAll: true},
|
||||
5: {start: "0%", end: "1%", selectAll: true},
|
||||
6: {start: "0in", end: "1in", selectAll: true},
|
||||
7: {start: "0cm", end: "1cm", selectAll: true},
|
||||
8: {start: "0mm", end: "1mm", selectAll: true},
|
||||
9: {start: "0ex", end: "1ex", selectAll: true}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function* testHexIncrements(view) {
|
||||
info("Testing keyboard increments with hex colors");
|
||||
|
@ -81,12 +81,12 @@ function* testHexIncrements(view) {
|
|||
yield runIncrementTest(hexColorPropEditor, view, {
|
||||
1: {start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
|
||||
2: {shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true},
|
||||
3: {start: "#CCCCCC", end: "#CDCCCC", selection: [1,3]},
|
||||
4: {shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1,3]},
|
||||
3: {start: "#CCCCCC", end: "#CDCCCC", selection: [1, 3]},
|
||||
4: {shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1, 3]},
|
||||
5: {start: "#FFFFFF", end: "#FFFFFF", selectAll: true},
|
||||
6: {down: true, shift: true, start: "#000000", end: "#000000", selectAll: true}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function* testRgbIncrements(view) {
|
||||
info("Testing keyboard increments with rgb colors");
|
||||
|
@ -95,14 +95,14 @@ function* testRgbIncrements(view) {
|
|||
let rgbColorPropEditor = idRuleEditor.rule.textProps[3].editor;
|
||||
|
||||
yield runIncrementTest(rgbColorPropEditor, view, {
|
||||
1: {start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6,7]},
|
||||
2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6,7]},
|
||||
3: {start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6,9]},
|
||||
4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6,9]},
|
||||
5: {down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6,7]},
|
||||
6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6,7]}
|
||||
1: {start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6, 7]},
|
||||
2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6, 7]},
|
||||
3: {start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6, 9]},
|
||||
4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6, 9]},
|
||||
5: {down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6, 7]},
|
||||
6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6, 7]}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function* testShorthandIncrements(view) {
|
||||
info("Testing keyboard increments within shorthand values");
|
||||
|
@ -111,17 +111,17 @@ function* testShorthandIncrements(view) {
|
|||
let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
|
||||
|
||||
yield runIncrementTest(paddingPropEditor, view, {
|
||||
1: {start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4,7]},
|
||||
2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4,7]},
|
||||
1: {start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4, 7]},
|
||||
2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4, 7]},
|
||||
3: {start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true},
|
||||
4: {shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true},
|
||||
5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8,11]},
|
||||
5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8, 11]},
|
||||
6: {down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true},
|
||||
7: {up: true, start: "0.1em .1em 0em 0em", end: "0.1em 1.1em 0em 0em", selection: [6, 9]},
|
||||
8: {up: true, alt: true, start: "0.1em .9em 0em 0em", end: "0.1em 1em 0em 0em", selection: [6, 9]},
|
||||
9: {up: true, shift: true, start: "0.2em .2em 0em 0em", end: "0.2em 10.2em 0em 0em", selection: [6, 9]}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function* testOddCases(view) {
|
||||
info("Testing some more odd cases");
|
||||
|
@ -130,32 +130,38 @@ function* testOddCases(view) {
|
|||
let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
|
||||
|
||||
yield runIncrementTest(marginPropEditor, view, {
|
||||
1: {start: "98.7%", end: "99.7%", selection: [3,3]},
|
||||
2: {alt: true, start: "98.7%", end: "98.8%", selection: [3,3]},
|
||||
1: {start: "98.7%", end: "99.7%", selection: [3, 3]},
|
||||
2: {alt: true, start: "98.7%", end: "98.8%", selection: [3, 3]},
|
||||
3: {start: "0", end: "1"},
|
||||
4: {down: true, start: "0", end: "-1"},
|
||||
5: {start: "'a=-1'", end: "'a=0'", selection: [4,4]},
|
||||
6: {start: "0 -1px", end: "0 0px", selection: [2,2]},
|
||||
7: {start: "url(-1)", end: "url(-1)", selection: [4,4]},
|
||||
8: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,11]},
|
||||
9: {start: "url('test1.png')", end: "url('test2.png')", selection: [9,9]},
|
||||
10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9,9]},
|
||||
11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9,11]},
|
||||
12: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,12]},
|
||||
13: {down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10,11]},
|
||||
14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10,14]}
|
||||
5: {start: "'a=-1'", end: "'a=0'", selection: [4, 4]},
|
||||
6: {start: "0 -1px", end: "0 0px", selection: [2, 2]},
|
||||
7: {start: "url(-1)", end: "url(-1)", selection: [4, 4]},
|
||||
8: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11, 11]},
|
||||
9: {start: "url('test1.png')", end: "url('test2.png')", selection: [9, 9]},
|
||||
10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9, 9]},
|
||||
11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9, 11]},
|
||||
12: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11, 12]},
|
||||
13: {down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10, 11]},
|
||||
14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10, 14]}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function* runIncrementTest(propertyEditor, view, tests) {
|
||||
let editor = yield focusEditableField(view, propertyEditor.valueSpan);
|
||||
|
||||
for(let test in tests) {
|
||||
for (let test in tests) {
|
||||
yield testIncrement(editor, tests[test], view, propertyEditor);
|
||||
}
|
||||
|
||||
// Blur the field to put back the UI in its initial state (and avoid pending
|
||||
// requests when the test ends).
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
|
||||
yield onRuleViewChanged;
|
||||
}
|
||||
|
||||
function* testIncrement(editor, options, view, {ruleEditor}) {
|
||||
function* testIncrement(editor, options, view) {
|
||||
editor.input.value = options.start;
|
||||
let input = editor.input;
|
||||
|
||||
|
|
|
@ -33,14 +33,16 @@ add_task(function*() {
|
|||
yield focusEditableField(view, propEditor.valueSpan);
|
||||
|
||||
info("Deleting all the text out of a value field");
|
||||
let waitForUpdates = view.once("ruleview-changed");
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
yield sendCharsAndWaitForFocus(view, ruleEditor.element,
|
||||
["VK_DELETE", "VK_RETURN"]);
|
||||
yield waitForUpdates;
|
||||
yield onRuleViewChanged;
|
||||
|
||||
info("Pressing enter a couple times to cycle through editors");
|
||||
yield sendCharsAndWaitForFocus(view, ruleEditor.element, ["VK_RETURN"]);
|
||||
onRuleViewChanged = view.once("ruleview-changed");
|
||||
yield sendCharsAndWaitForFocus(view, ruleEditor.element, ["VK_RETURN"]);
|
||||
yield onRuleViewChanged;
|
||||
|
||||
isnot(ruleEditor.rule.textProps[1].editor.nameSpan.style.display, "none",
|
||||
"The name span is visible");
|
||||
|
|
|
@ -19,25 +19,27 @@ add_task(function*() {
|
|||
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("#testid", inspector);
|
||||
yield testRenameProperty(inspector, view);
|
||||
});
|
||||
|
||||
function* testRenameProperty(inspector, view) {
|
||||
info("Get the color property editor");
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 0);
|
||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
||||
|
||||
is(ruleEditor.rule.textProps[0].name, "color");
|
||||
|
||||
info("Focus on property name");
|
||||
let editor = yield focusEditableField(ruleEditor.ruleView,
|
||||
propEditor.nameSpan, 32, 1);
|
||||
info("Focus the property name field");
|
||||
yield focusEditableField(ruleEditor.ruleView, propEditor.nameSpan, 32, 1);
|
||||
|
||||
info("Renaming the property");
|
||||
info("Rename the property to background-color");
|
||||
// Expect 3 events: the value editor being focused, the ruleview-changed event
|
||||
// which signals that the new value has been previewed (fires once when the
|
||||
// value gets focused), and the markupmutation event since we're modifying an
|
||||
// inline style.
|
||||
let onValueFocus = once(ruleEditor.element, "focus", true);
|
||||
let onModifications = ruleEditor.ruleView.once("ruleview-changed");
|
||||
let onRuleViewChanged = ruleEditor.ruleView.once("ruleview-changed");
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
EventUtils.sendString("background-color:", ruleEditor.doc.defaultView);
|
||||
yield onValueFocus;
|
||||
yield onModifications;
|
||||
yield onRuleViewChanged;
|
||||
yield onMutation;
|
||||
|
||||
is(ruleEditor.rule.textProps[0].name, "background-color");
|
||||
yield waitForComputedStyleProperty("#testid", null, "background-color",
|
||||
|
@ -45,4 +47,11 @@ function* testRenameProperty(inspector, view) {
|
|||
|
||||
is((yield getComputedStyleProperty("#testid", null, "color")),
|
||||
"rgb(255, 255, 255)", "color is white");
|
||||
}
|
||||
|
||||
// The value field is still focused. Blur it now and wait for the
|
||||
// ruleview-changed event to avoid pending requests.
|
||||
onRuleViewChanged = view.once("ruleview-changed");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
yield onRuleViewChanged;
|
||||
});
|
||||
|
||||
|
|
|
@ -57,6 +57,11 @@ function* testEditSelector(view, name) {
|
|||
ok(getRuleViewRule(view, name), "Rule with " + name + " selector exists.");
|
||||
ok(getRuleViewRuleEditor(view, 1).element.getAttribute("unmatched"),
|
||||
"Rule with " + name + " does not match the current element.");
|
||||
|
||||
// Escape the new property editor after editing the selector
|
||||
let onBlur = once(view.styleDocument.activeElement, "blur");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, view.styleWindow);
|
||||
yield onBlur;
|
||||
}
|
||||
|
||||
function* checkModifiedElement(view, name) {
|
||||
|
|
|
@ -30,51 +30,65 @@ add_task(function*() {
|
|||
yield testEditableFieldFocus(inspector, view, "VK_TAB");
|
||||
});
|
||||
|
||||
function* testEditableFieldFocus(inspector, view, commitKey, options={}) {
|
||||
function* testEditableFieldFocus(inspector, view, commitKey) {
|
||||
info("Click on the selector of the inline style ('element')");
|
||||
let ruleEditor = getRuleViewRuleEditor(view, 0);
|
||||
|
||||
let onFocus = once(ruleEditor.element, "focus", true);
|
||||
ruleEditor.selectorText.click();
|
||||
yield onFocus;
|
||||
assertEditor(view, ruleEditor.newPropSpan,
|
||||
"Focus should be in the element property span");
|
||||
|
||||
info("Focus the next field with " + commitKey);
|
||||
ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, ruleEditor.selectorText,
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey);
|
||||
assertEditor(view, ruleEditor.selectorText,
|
||||
"Focus should have moved to the next rule selector");
|
||||
|
||||
for (let textProp of ruleEditor.rule.textProps) {
|
||||
for (let i = 0; i < ruleEditor.rule.textProps.length; i++) {
|
||||
let textProp = ruleEditor.rule.textProps[i];
|
||||
let propEditor = textProp.editor;
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, propEditor.nameSpan,
|
||||
info("Focus the next field with " + commitKey);
|
||||
// Expect a ruleview-changed event if we are moving from a property value
|
||||
// to the next property name (which occurs after the first iteration, as for
|
||||
// i=0, the previous field is the selector).
|
||||
let onRuleViewChanged = i > 0 ? view.once("ruleview-changed") : null;
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey);
|
||||
yield onRuleViewChanged;
|
||||
assertEditor(view, propEditor.nameSpan,
|
||||
"Focus should have moved to the property name");
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, propEditor.valueSpan,
|
||||
info("Focus the next field with " + commitKey);
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey);
|
||||
assertEditor(view, propEditor.valueSpan,
|
||||
"Focus should have moved to the property value");
|
||||
}
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, ruleEditor.newPropSpan,
|
||||
// Expect a ruleview-changed event again as we're bluring a property value.
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey);
|
||||
yield onRuleViewChanged;
|
||||
assertEditor(view, ruleEditor.newPropSpan,
|
||||
"Focus should have moved to the new property span");
|
||||
|
||||
ruleEditor = getRuleViewRuleEditor(view, 2);
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, ruleEditor.selectorText,
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey);
|
||||
assertEditor(view, ruleEditor.selectorText,
|
||||
"Focus should have moved to the next rule selector");
|
||||
|
||||
info("Blur the selector field");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
}
|
||||
|
||||
function* focusNextEditableField(view, ruleEditor, commitKey, options) {
|
||||
function* focusNextEditableField(view, ruleEditor, commitKey) {
|
||||
let onFocus = once(ruleEditor.element, "focus", true);
|
||||
EventUtils.synthesizeKey(commitKey, options, view.styleWindow);
|
||||
EventUtils.synthesizeKey(commitKey, {}, view.styleWindow);
|
||||
yield onFocus;
|
||||
}
|
||||
|
||||
function* assertEditor(view, element, message) {
|
||||
function assertEditor(view, element, message) {
|
||||
let editor = inplaceEditor(view.styleDocument.activeElement);
|
||||
is(inplaceEditor(element), editor, message);
|
||||
}
|
||||
|
|
|
@ -37,36 +37,42 @@ function* testEditableFieldFocus(inspector, view, commitKey, options={}) {
|
|||
|
||||
ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield focusNextField(view, ruleEditor, commitKey, options);
|
||||
assertEditor(view, ruleEditor.newPropSpan,
|
||||
"Focus should have moved to the new property span");
|
||||
|
||||
for (let textProp of ruleEditor.rule.textProps.slice(0).reverse()) {
|
||||
let propEditor = textProp.editor;
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield focusNextField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, propEditor.valueSpan,
|
||||
"Focus should have moved to the property value");
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield focusNextFieldAndExpectChange(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, propEditor.nameSpan,
|
||||
"Focus should have moved to the property name");
|
||||
}
|
||||
|
||||
ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield focusNextField(view, ruleEditor, commitKey, options);
|
||||
yield assertEditor(view, ruleEditor.selectorText,
|
||||
"Focus should have moved to the '#testid' rule selector");
|
||||
|
||||
ruleEditor = getRuleViewRuleEditor(view, 0);
|
||||
|
||||
yield focusNextEditableField(view, ruleEditor, commitKey, options);
|
||||
yield focusNextField(view, ruleEditor, commitKey, options);
|
||||
assertEditor(view, ruleEditor.newPropSpan,
|
||||
"Focus should have moved to the new property span");
|
||||
}
|
||||
|
||||
function* focusNextEditableField(view, ruleEditor, commitKey, options) {
|
||||
function* focusNextFieldAndExpectChange(view, ruleEditor, commitKey, options) {
|
||||
let onRuleViewChanged = view.once("ruleview-changed");
|
||||
yield focusNextField(view, ruleEditor, commitKey, options);
|
||||
yield onRuleViewChanged;
|
||||
}
|
||||
|
||||
function* focusNextField(view, ruleEditor, commitKey, options) {
|
||||
let onFocus = once(ruleEditor.element, "focus", true);
|
||||
EventUtils.synthesizeKey(commitKey, options, view.styleWindow);
|
||||
yield onFocus;
|
||||
|
|
|
@ -11,11 +11,11 @@ add_task(function*() {
|
|||
yield addTab(TEST_URL);
|
||||
let {view} = yield openRuleView();
|
||||
|
||||
info("Getting the filter swatch element");
|
||||
info("Get the filter swatch element");
|
||||
let swatch = getRuleViewProperty(view, "body", "filter").valueSpan
|
||||
.querySelector(".ruleview-filterswatch");
|
||||
|
||||
let filterTooltip = view.tooltips.filterEditor;
|
||||
info("Click on the filter swatch element");
|
||||
// Clicking on a cssfilter swatch sets the current filter value in the tooltip
|
||||
// which, in turn, makes the FilterWidget emit an "updated" event that causes
|
||||
// the rule-view to refresh. So we must wait for the ruleview-changed event.
|
||||
|
@ -23,17 +23,20 @@ add_task(function*() {
|
|||
swatch.click();
|
||||
yield onRuleViewChanged;
|
||||
|
||||
info("Get the cssfilter widget instance");
|
||||
let filterTooltip = view.tooltips.filterEditor;
|
||||
let widget = yield filterTooltip.widget;
|
||||
|
||||
info("Set a new value in the cssfilter widget");
|
||||
onRuleViewChanged = view.once("ruleview-changed");
|
||||
widget.setCssValue("blur(2px)");
|
||||
yield waitForComputedStyleProperty("body", null, "filter", "blur(2px)");
|
||||
yield onRuleViewChanged;
|
||||
|
||||
ok(true, "Changes previewed on the element");
|
||||
|
||||
onRuleViewChanged = view.once("ruleview-changed");
|
||||
info("Pressing RETURN to commit changes");
|
||||
info("Press RETURN to commit changes");
|
||||
// Pressing return in the cssfilter tooltip triggeres 2 ruleview-changed
|
||||
onRuleViewChanged = waitForNEvents(view, "ruleview-changed", 2);
|
||||
EventUtils.sendKey("RETURN", widget.styleWindow);
|
||||
yield onRuleViewChanged;
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ add_task(function*() {
|
|||
is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
|
||||
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
|
||||
is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
|
||||
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
|
||||
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
|
||||
is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
|
||||
is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
|
||||
is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
|
||||
|
||||
info("Closing context menu");
|
||||
|
|
|
@ -97,8 +97,7 @@ function* checkSelectAll(view) {
|
|||
info("Checking that _SelectAll() then copy returns the correct " +
|
||||
"clipboard value");
|
||||
view._contextmenu._onSelectAll();
|
||||
let expectedPattern = "[\\r\\n]+" +
|
||||
"element {[\\r\\n]+" +
|
||||
let expectedPattern = "element {[\\r\\n]+" +
|
||||
" margin: 10em;[\\r\\n]+" +
|
||||
" font-size: 14pt;[\\r\\n]+" +
|
||||
" font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||
|
|
|
@ -48,11 +48,11 @@ addTab = function(url) {
|
|||
* view is visible and ready
|
||||
*/
|
||||
function openRuleView() {
|
||||
return openInspectorSidebarTab("ruleview").then(objects => {
|
||||
return openInspectorSidebarTab("ruleview").then(({toolbox, inspector}) => {
|
||||
return {
|
||||
toolbox: objects.toolbox,
|
||||
inspector: objects.inspector,
|
||||
view: objects.view.view
|
||||
toolbox,
|
||||
inspector,
|
||||
view: inspector.ruleview.view
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -369,7 +369,7 @@ StyleInspectorMenu.prototype = {
|
|||
*/
|
||||
_onSelectAll: function() {
|
||||
let selection = this.styleWindow.getSelection();
|
||||
selection.selectAllChildren(this.styleDocument.documentElement);
|
||||
selection.selectAllChildren(this.view.element);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,8 +19,7 @@ add_task(function*() {
|
|||
is(getRuleViewPropertyValue(view, "element", "color"), "red",
|
||||
"The rule-view shows the properties for test node one");
|
||||
|
||||
let cView = inspector.sidebar.getWindowForTab("computedview")
|
||||
.computedview.view;
|
||||
let cView = inspector.computedview.view;
|
||||
let prop = getComputedViewProperty(cView, "color");
|
||||
ok(!prop, "The computed-view doesn't show the properties for test node one");
|
||||
|
||||
|
|
|
@ -250,18 +250,13 @@ function waitForToolboxFrameFocus(toolbox) {
|
|||
var openInspectorSideBar = Task.async(function*(id) {
|
||||
let {toolbox, inspector} = yield openInspector();
|
||||
|
||||
if (!hasSideBarTab(inspector, id)) {
|
||||
info("Waiting for the " + id + " sidebar to be ready");
|
||||
yield inspector.sidebar.once(id + "-ready");
|
||||
}
|
||||
|
||||
info("Selecting the " + id + " sidebar");
|
||||
inspector.sidebar.select(id);
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector,
|
||||
view: inspector.sidebar.getWindowForTab(id)[id].view
|
||||
view: inspector[id].view
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -117,29 +117,24 @@ function* testBreadcrumbs(selector, inspector) {
|
|||
|
||||
function* clickOnInspectMenuItem(testActor, selector) {
|
||||
info("Showing the contextual menu on node " + selector);
|
||||
let contentAreaContextMenu = document.querySelector("#contentAreaContextMenu");
|
||||
let contextOpened = once(contentAreaContextMenu, "popupshown");
|
||||
|
||||
yield testActor.synthesizeMouse({
|
||||
selector: selector,
|
||||
center: true,
|
||||
options: {type: "contextmenu", button: 2}
|
||||
});
|
||||
|
||||
// nsContextMenu also requires the popupNode to be set, but we can't set it to
|
||||
// node under e10s as it's a CPOW, not a DOM node. But under e10s,
|
||||
// nsContextMenu won't use the property anyway, so just try/catching is ok.
|
||||
try {
|
||||
document.popupNode = content.document.querySelector(selector);
|
||||
} catch (e) {}
|
||||
|
||||
let contentAreaContextMenu = document.querySelector("#contentAreaContextMenu");
|
||||
let contextMenu = new nsContextMenu(contentAreaContextMenu);
|
||||
yield contextOpened;
|
||||
|
||||
info("Triggering inspect action and hiding the menu.");
|
||||
yield contextMenu.inspectNode();
|
||||
yield gContextMenu.inspectNode();
|
||||
|
||||
contentAreaContextMenu.hidden = true;
|
||||
let contextClosed = once(contentAreaContextMenu, "popuphidden");
|
||||
contentAreaContextMenu.hidePopup();
|
||||
contextMenu.hiding();
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield getActiveInspector().once("inspector-updated");
|
||||
yield contextClosed;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,10 @@ add_task(function*() {
|
|||
info("Creating the test tab and opening the rule-view");
|
||||
let {toolbox, inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let view = yield ensureRuleView(inspector);
|
||||
info("Selecting the ruleview sidebar");
|
||||
inspector.sidebar.select("ruleview");
|
||||
|
||||
let view = inspector.ruleview.view;
|
||||
|
||||
info("Selecting the test node");
|
||||
yield selectNode("#div-1", inspector);
|
||||
|
@ -134,15 +137,3 @@ function* assertPseudoRemovedFromView(inspector, testActor, ruleview) {
|
|||
is(value, "", "pseudo-class removed from infobar selector");
|
||||
yield inspector.toolbox.highlighter.hideBoxModel();
|
||||
}
|
||||
|
||||
function* ensureRuleView(inspector) {
|
||||
if (!inspector.sidebar.getWindowForTab("ruleview")) {
|
||||
info("Waiting for ruleview initialization to complete.");
|
||||
yield inspector.sidebar.once("ruleview-ready");
|
||||
}
|
||||
|
||||
info("Selecting the ruleview sidebar");
|
||||
inspector.sidebar.select("ruleview");
|
||||
|
||||
return inspector.sidebar.getWindowForTab("ruleview")["ruleview"].view;
|
||||
}
|
||||
|
|
|
@ -170,32 +170,15 @@ function getActiveInspector() {
|
|||
var openInspectorSidebarTab = Task.async(function*(id, hostType) {
|
||||
let {toolbox, inspector} = yield openInspector();
|
||||
|
||||
if (!hasSideBarTab(inspector, id)) {
|
||||
info("Waiting for the " + id + " sidebar to be ready");
|
||||
yield inspector.sidebar.once(id + "-ready");
|
||||
}
|
||||
|
||||
info("Selecting the " + id + " sidebar");
|
||||
inspector.sidebar.select(id);
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector,
|
||||
view: inspector.sidebar.getWindowForTab(id)[id]
|
||||
toolbox,
|
||||
inspector
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks whether the inspector's sidebar corresponding to the given id already
|
||||
* exists
|
||||
* @param {InspectorPanel}
|
||||
* @param {String}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function hasSideBarTab(inspector, id) {
|
||||
return !!inspector.sidebar.getWindowForTab(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NodeFront for a node that matches a given css selector, via the
|
||||
* protocol.
|
||||
|
|
|
@ -26,14 +26,9 @@ devtools.jar:
|
|||
content/styleeditor/styleeditor.xul (styleeditor/styleeditor.xul)
|
||||
content/styleeditor/styleeditor.css (styleeditor/styleeditor.css)
|
||||
content/storage/storage.xul (storage/storage.xul)
|
||||
content/inspector/computed/computed.xhtml (inspector/computed/computed.xhtml)
|
||||
content/inspector/fonts/fonts.js (inspector/fonts/fonts.js)
|
||||
content/inspector/fonts/fonts.xhtml (inspector/fonts/fonts.xhtml)
|
||||
content/inspector/layout/layout.js (inspector/layout/layout.js)
|
||||
content/inspector/layout/layout.xhtml (inspector/layout/layout.xhtml)
|
||||
content/inspector/markup/markup.css (inspector/markup/markup.css)
|
||||
content/inspector/markup/markup.xhtml (inspector/markup/markup.xhtml)
|
||||
content/inspector/rules/rules.xhtml (inspector/rules/rules.xhtml)
|
||||
content/animationinspector/animation-controller.js (animationinspector/animation-controller.js)
|
||||
content/animationinspector/animation-panel.js (animationinspector/animation-panel.js)
|
||||
content/animationinspector/animation-inspector.xhtml (animationinspector/animation-inspector.xhtml)
|
||||
|
|
|
@ -27,7 +27,7 @@ Object.defineProperty(exports, "TargetFactory", {
|
|||
});
|
||||
|
||||
const unloadObserver = {
|
||||
observe: function(subject, topic, data) {
|
||||
observe: function(subject) {
|
||||
if (subject.wrappedJSObject === require("@loader/unload")) {
|
||||
Services.obs.removeObserver(unloadObserver, "sdk:loader:destroy");
|
||||
for (let definition of gDevTools.getToolDefinitionArray()) {
|
||||
|
|
|
@ -253,7 +253,9 @@ var NetMonitorController = {
|
|||
this._disconnection = promise.defer();
|
||||
|
||||
// Wait for the connection to finish first.
|
||||
yield this._connection.promise;
|
||||
if (!this.isConnected()) {
|
||||
yield this._connection.promise;
|
||||
}
|
||||
|
||||
// When debugging local or a remote instance, the connection is closed by
|
||||
// the RemoteTarget. The webconsole actor is stopped on disconnect.
|
||||
|
|
|
@ -17,6 +17,9 @@ pref("devtools.devedition.promo.url", "https://www.mozilla.org/firefox/developer
|
|||
// Disable the error console
|
||||
pref("devtools.errorconsole.enabled", false);
|
||||
|
||||
// DevTools development workflow
|
||||
pref("devtools.loader.hotreload", false);
|
||||
|
||||
// Developer toolbar preferences
|
||||
pref("devtools.toolbar.enabled", true);
|
||||
pref("devtools.toolbar.visible", false);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<?xml-stylesheet href="chrome://devtools/skin/projecteditor/projecteditor.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/debugger/debugger.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/content/inspector/markup/markup.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/markup.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/* TODO: Bug 1242584 should make the following comment unnecessary */
|
||||
/* import-globals-from ../../../framework/test/shared-redux-head.js */
|
||||
|
||||
// Test viewports basics after opening, like size and location
|
||||
|
||||
const TEST_URL = "http://example.org/";
|
||||
|
|
|
@ -125,18 +125,13 @@ function waitForToolboxFrameFocus(toolbox) {
|
|||
var openInspectorSideBar = Task.async(function*(id) {
|
||||
let {toolbox, inspector} = yield openInspector();
|
||||
|
||||
if (!hasSideBarTab(inspector, id)) {
|
||||
info("Waiting for the " + id + " sidebar to be ready");
|
||||
yield inspector.sidebar.once(id + "-ready");
|
||||
}
|
||||
|
||||
info("Selecting the " + id + " sidebar");
|
||||
inspector.sidebar.select(id);
|
||||
|
||||
return {
|
||||
toolbox: toolbox,
|
||||
inspector: inspector,
|
||||
view: inspector.sidebar.getWindowForTab(id)[id].view
|
||||
view: inspector[id].view
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
const loaders = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
|
||||
const { devtools, DevToolsLoader } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { joinURI } = devtools.require("devtools/shared/path");
|
||||
const { Services } = devtools.require("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
const BROWSER_BASED_DIRS = [
|
||||
|
@ -17,6 +18,40 @@ const BROWSER_BASED_DIRS = [
|
|||
"resource://devtools/client/shared/redux"
|
||||
];
|
||||
|
||||
function clearCache() {
|
||||
Services.obs.notifyObservers(null, "startupcache-invalidate", null);
|
||||
}
|
||||
|
||||
function hotReloadFile(window, require, loader, componentProxies, fileURI) {
|
||||
dump("Hot reloading: " + fileURI + "\n");
|
||||
|
||||
if (fileURI.match(/\.js$/)) {
|
||||
// Test for React proxy components
|
||||
const proxy = componentProxies.get(fileURI);
|
||||
if (proxy) {
|
||||
// Remove the old module and re-require the new one; the require
|
||||
// hook in the loader will take care of the rest
|
||||
delete loader.modules[fileURI];
|
||||
clearCache();
|
||||
require(fileURI);
|
||||
}
|
||||
} else if (fileURI.match(/\.css$/)) {
|
||||
const links = [...window.document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "link")];
|
||||
links.forEach(link => {
|
||||
if (link.href.indexOf(fileURI) === 0) {
|
||||
const parentNode = link.parentNode;
|
||||
const newLink = window.document.createElementNS("http://www.w3.org/1999/xhtml", "link");
|
||||
newLink.rel = "stylesheet";
|
||||
newLink.type = "text/css";
|
||||
newLink.href = fileURI + "?s=" + Math.random();
|
||||
|
||||
parentNode.insertBefore(newLink, link);
|
||||
parentNode.removeChild(link);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a loader to be used in a browser environment. This evaluates
|
||||
* modules in their own environment, but sets window (the normal
|
||||
|
@ -45,6 +80,8 @@ const BROWSER_BASED_DIRS = [
|
|||
function BrowserLoader(baseURI, window) {
|
||||
const loaderOptions = devtools.require("@loader/options");
|
||||
const dynamicPaths = {};
|
||||
const componentProxies = new Map();
|
||||
const hotReloadEnabled = Services.prefs.getBoolPref("devtools.loader.hotreload");
|
||||
|
||||
if(AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES) {
|
||||
dynamicPaths["devtools/client/shared/vendor/react"] =
|
||||
|
@ -81,12 +118,47 @@ function BrowserLoader(baseURI, window) {
|
|||
}
|
||||
};
|
||||
|
||||
if(hotReloadEnabled) {
|
||||
opts.loadModuleHook = (module, require) => {
|
||||
const { uri, exports } = module;
|
||||
|
||||
if (exports.prototype &&
|
||||
exports.prototype.isReactComponent) {
|
||||
const { createProxy, getForceUpdate } =
|
||||
require("devtools/client/shared/vendor/react-proxy");
|
||||
const React = require("devtools/client/shared/vendor/react");
|
||||
|
||||
if (!componentProxies.get(uri)) {
|
||||
const proxy = createProxy(exports);
|
||||
componentProxies.set(uri, proxy);
|
||||
module.exports = proxy.get();
|
||||
}
|
||||
else {
|
||||
const proxy = componentProxies.get(uri);
|
||||
const instances = proxy.update(exports);
|
||||
instances.forEach(getForceUpdate(React));
|
||||
module.exports = proxy.get();
|
||||
}
|
||||
}
|
||||
return exports;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const mainModule = loaders.Module(baseURI, joinURI(baseURI, "main.js"));
|
||||
const mainLoader = loaders.Loader(opts);
|
||||
const require = loaders.Require(mainLoader, mainModule);
|
||||
|
||||
if(hotReloadEnabled) {
|
||||
const watcher = devtools.require("devtools/client/shared/file-watcher");
|
||||
watcher.on("file-changed", (_, fileURI) => {
|
||||
hotReloadFile(window, require, mainLoader, componentProxies, fileURI);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
loader: mainLoader,
|
||||
require: loaders.Require(mainLoader, mainModule)
|
||||
require: require
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
/* eslint-env worker */
|
||||
/* global OS */
|
||||
importScripts("resource://gre/modules/osfile.jsm");
|
||||
|
||||
const modifiedTimes = new Map();
|
||||
|
||||
function gatherFiles(path, fileRegex) {
|
||||
let files = [];
|
||||
const iterator = new OS.File.DirectoryIterator(path);
|
||||
|
||||
try {
|
||||
for (let child in iterator) {
|
||||
// Don't descend into test directories. Saves us some time and
|
||||
// there's no reason to.
|
||||
if (child.isDir && !child.path.endsWith("/test")) {
|
||||
files = files.concat(gatherFiles(child.path, fileRegex));
|
||||
} else if (child.path.match(fileRegex)) {
|
||||
let info;
|
||||
try {
|
||||
info = OS.File.stat(child.path);
|
||||
} catch (e) {
|
||||
// Just ignore it.
|
||||
continue;
|
||||
}
|
||||
|
||||
files.push(child.path);
|
||||
modifiedTimes.set(child.path, info.lastModificationDate.getTime());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
function scanFiles(files, onChangedFile) {
|
||||
files.forEach(file => {
|
||||
let info;
|
||||
try {
|
||||
info = OS.File.stat(file);
|
||||
} catch (e) {
|
||||
// Just ignore it. It was probably deleted.
|
||||
return;
|
||||
}
|
||||
|
||||
const lastTime = modifiedTimes.get(file);
|
||||
|
||||
if (info.lastModificationDate.getTime() > lastTime) {
|
||||
modifiedTimes.set(file, info.lastModificationDate.getTime());
|
||||
onChangedFile(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onmessage = function(event) {
|
||||
const { path, fileRegex } = event.data;
|
||||
let info = OS.File.stat(path);
|
||||
if (!info.isDir) {
|
||||
throw new Error("watcher expects a directory as root path");
|
||||
}
|
||||
|
||||
// We get a list of all the files upfront, which means we don't
|
||||
// support adding new files. But you need to rebuild Firefox when
|
||||
// adding a new file anyway.
|
||||
const files = gatherFiles(path, fileRegex || /.*/);
|
||||
|
||||
// Every second, scan for file changes by stat-ing each of them and
|
||||
// comparing modification time.
|
||||
setInterval(() => {
|
||||
scanFiles(files, changedFile => postMessage(changedFile));
|
||||
}, 1000);
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Ci, ChromeWorker } = require("chrome");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
|
||||
const HOTRELOAD_PREF = "devtools.loader.hotreload";
|
||||
|
||||
function resolveResourceURI(uri) {
|
||||
const handler = Services.io.getProtocolHandler("resource")
|
||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
||||
return handler.resolveURI(Services.io.newURI(uri, null, null));
|
||||
}
|
||||
|
||||
function watchFiles(path, onFileChanged) {
|
||||
if (!path.startsWith("devtools/")) {
|
||||
throw new Error("`watchFiles` expects a devtools path");
|
||||
}
|
||||
|
||||
// We need to figure out a local path to watch. We start with
|
||||
// whatever devtools points to.
|
||||
let resolvedRootURI = resolveResourceURI("resource://devtools");
|
||||
if (resolvedRootURI.match(/\/obj\-.*/)) {
|
||||
// Move from the built directory to the user's local files
|
||||
resolvedRootURI = resolvedRootURI.replace(/\/obj\-.*/, "") + "/devtools";
|
||||
}
|
||||
resolvedRootURI = resolvedRootURI.replace(/^file:\/\//, "");
|
||||
const localURI = resolvedRootURI + "/" + path.replace(/^devtools\//, "");
|
||||
|
||||
const watchWorker = new ChromeWorker(
|
||||
"resource://devtools/client/shared/file-watcher-worker.js"
|
||||
);
|
||||
|
||||
watchWorker.onmessage = event => {
|
||||
// We need to turn a local path back into a resource URI (or
|
||||
// chrome). This means that this system will only work when built
|
||||
// files are symlinked, so that these URIs actually read from
|
||||
// local sources. There might be a better way to do this.
|
||||
const relativePath = event.data.replace(resolvedRootURI + "/", "");
|
||||
if (relativePath.startsWith("client/themes")) {
|
||||
onFileChanged(relativePath.replace("client/themes",
|
||||
"chrome://devtools/skin"));
|
||||
}
|
||||
onFileChanged("resource://devtools/" + relativePath);
|
||||
};
|
||||
|
||||
watchWorker.postMessage({ path: localURI, fileRegex: /\.(js|css)$/ });
|
||||
return watchWorker;
|
||||
}
|
||||
|
||||
EventEmitter.decorate(module.exports);
|
||||
|
||||
let watchWorker;
|
||||
function onPrefChange() {
|
||||
if (Services.prefs.getBoolPref(HOTRELOAD_PREF) && !watchWorker) {
|
||||
watchWorker = watchFiles("devtools/client", changedFile => {
|
||||
module.exports.emit("file-changed", changedFile);
|
||||
});
|
||||
}
|
||||
else if(watchWorker) {
|
||||
watchWorker.terminate();
|
||||
watchWorker = null;
|
||||
}
|
||||
}
|
||||
|
||||
Services.prefs.addObserver(HOTRELOAD_PREF, {
|
||||
observe: onPrefChange
|
||||
}, false);
|
||||
|
||||
onPrefChange();
|
|
@ -25,6 +25,8 @@ DevToolsModules(
|
|||
'devices.js',
|
||||
'DOMHelpers.jsm',
|
||||
'doorhanger.js',
|
||||
'file-watcher-worker.js',
|
||||
'file-watcher.js',
|
||||
'frame-script-utils.js',
|
||||
'getjson.js',
|
||||
'inplace-editor.js',
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
|
||||
modules = []
|
||||
|
||||
# react-dev is used if either debug mode is enabled,
|
||||
# so include it for both
|
||||
if CONFIG['DEBUG_JS_MODULES'] or CONFIG['MOZ_DEBUG']:
|
||||
modules += ['react-dev.js']
|
||||
|
||||
modules += [
|
||||
'react-dom.js',
|
||||
'react-proxy.js',
|
||||
'react-redux.js',
|
||||
'react.js',
|
||||
'redux.js',
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -197,8 +197,12 @@ add_task(function*() {
|
|||
|
||||
yield findVariableViewProperties([{name: "ss2", value: "changed=ss2"}]);
|
||||
|
||||
// Clearing items
|
||||
yield gWindow.clear();
|
||||
// Clearing items. Bug 1233497 makes it so that we can no longer yield
|
||||
// CPOWs from Tasks. We work around this by calling clear via a ContentTask
|
||||
// instead.
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
|
||||
return Task.spawn(content.wrappedJSObject.clear);
|
||||
});
|
||||
|
||||
yield gUI.once("store-objects-cleared");
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче